From 6c9387d603f8ad0bdbecd2831a01b1d1932ddef3 Mon Sep 17 00:00:00 2001 From: Tomasz Socha Date: Mon, 10 May 2021 12:09:52 +0200 Subject: [PATCH 01/99] [ONNX Importer] Fix dynamism for grouped conv(transpose) operators (#5540) --- ngraph/frontend/onnx_import/src/op/conv.cpp | 6 +- .../onnx_import/src/op/conv_transpose.cpp | 60 +------------------ .../onnx_import/src/utils/convpool.cpp | 24 ++++++++ .../onnx_import/src/utils/convpool.hpp | 10 ++++ 4 files changed, 36 insertions(+), 64 deletions(-) diff --git a/ngraph/frontend/onnx_import/src/op/conv.cpp b/ngraph/frontend/onnx_import/src/op/conv.cpp index 0b5eed22a83..2a2cab12016 100644 --- a/ngraph/frontend/onnx_import/src/op/conv.cpp +++ b/ngraph/frontend/onnx_import/src/op/conv.cpp @@ -37,12 +37,8 @@ namespace ngraph { if (groups > 1) { - auto filters_shape = filters.get_shape(); - filters_shape.at(0) = filters_shape.at(0) / groups; - filters_shape.insert(filters_shape.begin(), groups); - const auto reshaped_filters = - ngraph::builder::opset1::reshape(filters, filters_shape); + convpool::get_reshaped_filters(filters, groups); return std::make_shared( data, diff --git a/ngraph/frontend/onnx_import/src/op/conv_transpose.cpp b/ngraph/frontend/onnx_import/src/op/conv_transpose.cpp index 455b14b4d68..8f50856f7da 100644 --- a/ngraph/frontend/onnx_import/src/op/conv_transpose.cpp +++ b/ngraph/frontend/onnx_import/src/op/conv_transpose.cpp @@ -112,61 +112,6 @@ namespace ngraph } } - Output get_reshaped_filters(const Output& filters, - const PartialShape& filters_pshape, - int64_t groups) - { - if (filters_pshape.is_static()) - { - Shape new_filters_shape{filters_pshape.to_shape()}; - new_filters_shape.at(0) /= groups; - new_filters_shape.insert(std::begin(new_filters_shape), groups); - return builder::opset1::reshape(filters, new_filters_shape); - } - else - { - // TODO: Following should go to some helper like - // split_shape_into_parts(axis) - // Split filters shape into two parts: (first_dim, the_rest_of_dims) - const auto filters_shape = - std::make_shared(filters); - const auto filters_rank = - std::make_shared(filters_shape); - const auto one_node = - default_opset::Constant::create(element::i64, Shape{1}, {1}); - const auto zero_node = - default_opset::Constant::create(element::i64, Shape{1}, {0}); - - std::shared_ptr in_c_dim = - std::make_shared( - filters_shape, - zero_node, // begin - one_node, // end - std::vector{0}, // begin mask - std::vector{0}); // end mask - - const auto remaining_dims = - std::make_shared( - filters_shape, - one_node, // begin - filters_rank, // end - std::vector{0}, // begin mask - std::vector{0}); // end mask - - // Apply shape layout transformation: - const auto groups_node = - default_opset::Constant::create(element::i64, Shape{1}, {groups}); - in_c_dim = - std::make_shared(in_c_dim, groups_node); - - const auto new_filters_shape = std::make_shared( - OutputVector{groups_node, in_c_dim, remaining_dims}, 0); - return std::make_shared( - filters, new_filters_shape, false) - ->add_provenance_group_members_above({filters}); - } - } - Output get_prepared_bias(const Output& bias, const Output& conv) { @@ -279,12 +224,9 @@ namespace ngraph Output conv_node; - // reshape filters to match desired shape: - // [GROUPS, C_INPUT, C_OUTPUT, K_D, ..., K_1] - // from [C_INPUT x C_OUTPUT/groups x k1 x k2 x ... x kn] if (groups > 1) { - filters = get_reshaped_filters(filters, filters_pshape, groups); + filters = convpool::get_reshaped_filters(filters, groups); conv_node = make_group_conv_backprop(data, filters, strides, diff --git a/ngraph/frontend/onnx_import/src/utils/convpool.cpp b/ngraph/frontend/onnx_import/src/utils/convpool.cpp index 1afb78acbf6..64644c5e11e 100644 --- a/ngraph/frontend/onnx_import/src/utils/convpool.cpp +++ b/ngraph/frontend/onnx_import/src/utils/convpool.cpp @@ -4,6 +4,7 @@ #include +#include "default_opset.hpp" #include "exceptions.hpp" #include "ngraph/op/util/attr_types.hpp" #include "ngraph/strides.hpp" @@ -180,6 +181,29 @@ namespace ngraph } } + Output get_reshaped_filters(const Output& filters, + int64_t groups) + { + const auto zero_node = default_opset::Constant::create(element::i64, Shape(), {0}); + const auto split_lengths = + default_opset::Constant::create(element::i64, Shape{2}, {1, -1}); + const auto groups_node = + default_opset::Constant::create(element::i64, Shape{1}, {groups}); + + const auto filters_shape = std::make_shared(filters); + const auto splitted_shape = std::make_shared( + filters_shape, zero_node, split_lengths); + + const auto first_dim = + std::make_shared(splitted_shape->output(0), groups_node); + const auto new_filters_shape = std::make_shared( + OutputVector{groups_node, first_dim, splitted_shape->output(1)}, 0); + + const auto reshaped_filters = + std::make_shared(filters, new_filters_shape, false); + + return reshaped_filters; + } } // namespace convpool } // namespace onnx_import } // namespace ngraph diff --git a/ngraph/frontend/onnx_import/src/utils/convpool.hpp b/ngraph/frontend/onnx_import/src/utils/convpool.hpp index f5de4dacd4a..62fbc3f1d28 100644 --- a/ngraph/frontend/onnx_import/src/utils/convpool.hpp +++ b/ngraph/frontend/onnx_import/src/utils/convpool.hpp @@ -100,6 +100,16 @@ namespace ngraph /// ngraph::op::PadType get_auto_pad(const Node& node); + /// \brief Reshape group convolution filters to match desired shape: + /// from [C_INPUT x C_OUTPUT/groups x k1 x k2 x ... x kn] + /// to [GROUPS, C_INPUT, C_OUTPUT, K_D, ..., K_1] + /// + /// \param[in] filters Filter input to reshape + /// \param[in] groups Number of groups + /// + /// \return Reshaped filters input. + Output get_reshaped_filters(const Output& filters, + int64_t groups); } // namespace convpool } // namespace onnx_import From 66b3efbb6cc3f5c08f482e43dd370a38684f185a Mon Sep 17 00:00:00 2001 From: Bartosz Lesniewski Date: Mon, 10 May 2021 12:37:18 +0200 Subject: [PATCH 02/99] Revise Squeeze op - tests (#5336) --- .../serialization/single_layer/squeeze.cpp | 46 +++++++++++++++++++ .../single_layer_tests/squeeze_unsqueeze.cpp | 12 ++--- .../single_layer_tests/squeeze_unsqueeze.cpp | 12 ++--- .../single_layer/squeeze_unsqueeze.hpp | 2 +- .../src/single_layer/squeeze_unsqueeze.cpp | 11 ++++- .../layer_tests_summary/utils/constants.py | 1 + ngraph/test/CMakeLists.txt | 1 + ngraph/test/visitors/op/squeeze.cpp | 28 +++++++++++ 8 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 inference-engine/tests/functional/inference_engine/serialization/single_layer/squeeze.cpp create mode 100644 ngraph/test/visitors/op/squeeze.cpp diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/squeeze.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/squeeze.cpp new file mode 100644 index 00000000000..126f01f2a0d --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/squeeze.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "shared_test_classes/single_layer/squeeze_unsqueeze.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +namespace { +TEST_P(SqueezeUnsqueezeLayerTest, Serialize) { + Serialize(); +} + +std::map, std::vector>> axesVectors = { + {{1, 1, 1, 1}, {{}, {-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {0, 1, 2}, {0, 2, 3}, {1, 2, 3}, {0, 1, 2, 3}}}, + {{1, 2, 3, 4}, {{}, {0}}}, + {{2, 1, 3, 4}, {{}, {1}}}, + {{1}, {{}, {-1}, {0}}}, + {{1, 2}, {{}, {0}}}, + {{2, 1}, {{}, {1}, {-1}}}, +}; + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::U32}; + +const std::vector opTypes = { + ngraph::helpers::SqueezeOpType::SQUEEZE}; + +INSTANTIATE_TEST_CASE_P(smoke_Squeeze_Basic, SqueezeUnsqueezeLayerTest, + ::testing::Combine( + ::testing::ValuesIn(CommonTestUtils::combineParams(axesVectors)), + ::testing::ValuesIn(opTypes), + ::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(CommonTestUtils::DEVICE_CPU)), + SqueezeUnsqueezeLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp index 486d0e20e47..1b1944f44f0 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp @@ -11,12 +11,12 @@ using namespace LayerTestsDefinitions; namespace { std::map, std::vector>> axesVectors = { - {{1, 1, 1, 1}, {{-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {0, 1, 2}, {0, 2, 3}, {1, 2, 3}, {0, 1, 2, 3}}}, - {{1, 2, 3, 4}, {{0}}}, - {{2, 1, 3, 4}, {{1}}}, - {{1}, {{-1}, {0}}}, - {{1, 2}, {{0}}}, - {{2, 1}, {{1}, {-1}}}, + {{1, 1, 1, 1}, {{}, {-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {0, 1, 2}, {0, 2, 3}, {1, 2, 3}, {0, 1, 2, 3}}}, + {{1, 2, 3, 4}, {{}, {0}}}, + {{2, 1, 3, 4}, {{}, {1}}}, + {{1}, {{}, {-1}, {0}}}, + {{1, 2}, {{}, {0}}}, + {{2, 1}, {{}, {1}, {-1}}}, }; const std::vector netPrecisions = { diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp index ab82ff49f12..365282fc772 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp @@ -11,12 +11,12 @@ using namespace LayerTestsDefinitions; namespace { std::map, std::vector>> axesVectors = { - {{1, 1, 1, 1}, {{-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}} }, - {{1, 2, 3, 4}, {{0}}}, - {{2, 1, 3, 4}, {{1}}}, - {{1}, {{-1}, {0}}}, - {{1, 2}, {{0}}}, - {{2, 1}, {{1}, {-1}}}, + {{1, 1, 1, 1}, {{}, {-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}}}, + {{1, 2, 3, 4}, {{}, {0}}}, + {{2, 1, 3, 4}, {{}, {1}}}, + {{1}, {{}, {-1}, {0}}}, + {{1, 2}, {{}, {0}}}, + {{2, 1}, {{}, {1}, {-1}}}, }; const std::vector netPrecisions = { diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/squeeze_unsqueeze.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/squeeze_unsqueeze.hpp index 05dd7cfab3a..6dd1d0dad90 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/squeeze_unsqueeze.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/squeeze_unsqueeze.hpp @@ -16,7 +16,7 @@ namespace LayerTestsDefinitions { using ShapeAxesTuple = std::pair, std::vector>; typedef std::tuple< - ShapeAxesTuple, // InputShape, Squeeze indexes + ShapeAxesTuple, // InputShape (required), Squeeze indexes (if empty treated as non-existent) ngraph::helpers::SqueezeOpType, // OpType InferenceEngine::Precision, // Net precision InferenceEngine::Precision, // Input precision diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/squeeze_unsqueeze.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/squeeze_unsqueeze.cpp index 5ea46aee664..d5108a05515 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/squeeze_unsqueeze.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/squeeze_unsqueeze.cpp @@ -18,7 +18,7 @@ std::string SqueezeUnsqueezeLayerTest::getTestCaseName(testing::TestParamInfo(); + const auto data_node = make_shared(element::f32, Shape{1}); + const auto squeeze = make_shared(data_node); + + NodeBuilder builder(squeeze); + const auto expected_attr_count = 0; + + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); +} From cd48b2f6ec990a7663d392817aca44f537b1f5a5 Mon Sep 17 00:00:00 2001 From: Piotr Szmelczynski Date: Tue, 11 May 2021 07:47:42 +0200 Subject: [PATCH 03/99] move elu unit-tests from fused_op.in.cpp to elu.in.cpp (#5512) --- ngraph/test/CMakeLists.txt | 1 + ngraph/test/backend/elu.in.cpp | 58 +++++++++++++++++++++++++++++ ngraph/test/backend/fused_op.in.cpp | 26 ------------- 3 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 ngraph/test/backend/elu.in.cpp diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 09f7e06011c..6347b884b81 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -337,6 +337,7 @@ set(MULTI_TEST_SRC backend/dyn_reshape.in.cpp backend/strided_slice.in.cpp backend/dynamic.in.cpp + backend/elu.in.cpp backend/erf.in.cpp backend/exp.in.cpp backend/floor.in.cpp diff --git a/ngraph/test/backend/elu.in.cpp b/ngraph/test/backend/elu.in.cpp new file mode 100644 index 00000000000..26ca60217e9 --- /dev/null +++ b/ngraph/test/backend/elu.in.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include +#include + +// clang-format off +#ifdef ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS +#define DEFAULT_FLOAT_TOLERANCE_BITS ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS +#endif + +#ifdef ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS +#define DEFAULT_DOUBLE_TOLERANCE_BITS ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS +#endif +// clang-format on + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "util/engine/test_engines.hpp" +#include "util/test_case.hpp" +#include "util/test_control.hpp" + +using namespace std; +using namespace ngraph; + +static string s_manifest = "${MANIFEST}"; +using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); + +NGRAPH_TEST(${BACKEND_NAME}, elu) +{ + auto A = make_shared(element::f32, Shape{3, 2}); + auto elu = make_shared(A, 0.5f); + auto function = make_shared(NodeVector{elu}, ParameterVector{A}); + + auto test_case = test::TestCase(function); + test_case.add_input(vector{-2.f, 3.f, -2.f, 1.f, -1.f, 0.f}); + test_case.add_expected_output( + vector{-0.432332358f, 3.f, -0.432332358f, 1.f, -0.316060279f, 0.f}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, elu_negative_alpha) +{ + auto A = make_shared(element::f32, Shape{3, 2}); + auto elu = make_shared(A, -1.f); + auto function = make_shared(NodeVector{elu}, ParameterVector{A}); + + auto test_case = test::TestCase(function); + test_case.add_input(vector{-2.f, 3.f, -2.f, 1.f, -1.f, 0.f}); + test_case.add_expected_output( + vector{0.864664717f, 3.f, 0.864664717f, 1.f, 0.632120559f, 0.f}); + test_case.run(); +} \ No newline at end of file diff --git a/ngraph/test/backend/fused_op.in.cpp b/ngraph/test/backend/fused_op.in.cpp index c1fe5a35797..567b590b24e 100644 --- a/ngraph/test/backend/fused_op.in.cpp +++ b/ngraph/test/backend/fused_op.in.cpp @@ -41,32 +41,6 @@ static string s_manifest = "${MANIFEST}"; using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); -NGRAPH_TEST(${BACKEND_NAME}, elu) -{ - auto A = make_shared(element::f32, Shape{3, 2}); - auto elu = make_shared(A, 0.5f); - auto function = make_shared(NodeVector{elu}, ParameterVector{A}); - - auto test_case = test::TestCase(function); - test_case.add_input(vector{-2.f, 3.f, -2.f, 1.f, -1.f, 0.f}); - test_case.add_expected_output( - vector{-0.432332358f, 3.f, -0.432332358f, 1.f, -0.316060279f, 0.f}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, elu_negative_alpha) -{ - auto A = make_shared(element::f32, Shape{3, 2}); - auto elu = make_shared(A, -1.f); - auto function = make_shared(NodeVector{elu}, ParameterVector{A}); - - auto test_case = test::TestCase(function); - test_case.add_input(vector{-2.f, 3.f, -2.f, 1.f, -1.f, 0.f}); - test_case.add_expected_output( - vector{0.864664717f, 3.f, 0.864664717f, 1.f, 0.632120559f, 0.f}); - test_case.run(); -} - NGRAPH_TEST(${BACKEND_NAME}, prelu) { Shape shape{3, 2}; From f089c40bb4e7889af41797d8ba0e74dc97f90a3e Mon Sep 17 00:00:00 2001 From: Patryk Elszkowski Date: Tue, 11 May 2021 07:53:08 +0200 Subject: [PATCH 04/99] update tanh reference implementation (#5478) Co-authored-by: Patryk Elszkowski --- .../include/ngraph/runtime/reference/tanh.hpp | 12 ++++++- ngraph/test/backend/tanh.in.cpp | 34 +++++++++++++++---- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/tanh.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/tanh.hpp index f78435352cb..9638d4d3bfd 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/tanh.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/tanh.hpp @@ -13,7 +13,8 @@ namespace ngraph { namespace reference { - template + template ::value, bool>::type = true> void tanh(const T* arg, T* out, size_t count) { for (size_t i = 0; i < count; i++) @@ -21,6 +22,15 @@ namespace ngraph out[i] = std::tanh(arg[i]); } } + template ::value, bool>::type = true> + void tanh(const T* arg, T* out, size_t count) + { + for (size_t i = 0; i < count; i++) + { + out[i] = std::roundl(std::tanh(arg[i])); + } + } } // namespace reference } // namespace runtime } // namespace ngraph diff --git a/ngraph/test/backend/tanh.in.cpp b/ngraph/test/backend/tanh.in.cpp index cdc65cd78db..4382d1b81b3 100644 --- a/ngraph/test/backend/tanh.in.cpp +++ b/ngraph/test/backend/tanh.in.cpp @@ -34,9 +34,9 @@ using namespace ngraph; static string s_manifest = "${MANIFEST}"; -NGRAPH_TEST(${BACKEND_NAME}, tanh) +NGRAPH_TEST(${BACKEND_NAME}, tanh_f32) { - Shape shape{6}; + Shape shape{8}; auto A = make_shared(element::f32, shape); auto f = make_shared(make_shared(A), ParameterVector{A}); @@ -44,14 +44,36 @@ NGRAPH_TEST(${BACKEND_NAME}, tanh) // Create some tensors for input/output auto a = backend->create_tensor(element::f32, shape); - vector input{1.0f, 0.0f, -0.0f, -1.0f, 0.5f, -0.5f}; + const vector input{2.f, 1.f, 0.5f, 0.f, -0.f, -0.5f, -1.f, -2.f}; + const auto expected = [&]{ + vector e(input.size(),0); + std::transform(begin(input), end(input), begin(e), [](float v){return std::tanh(v);}); + return e; + }(); copy_data(a, input); auto result = backend->create_tensor(element::f32, shape); - std::transform( - input.begin(), input.end(), input.begin(), [](float x) -> float { return tanhf(x); }); + auto handle = backend->compile(f); + handle->call_with_validate({result}, {a}); + EXPECT_TRUE(test::all_close_f(expected, read_vector(result))); +} + +NGRAPH_TEST(${BACKEND_NAME}, tanh_int32) +{ + Shape shape{5}; + auto A = make_shared(element::i32, shape); + auto f = make_shared(make_shared(A), ParameterVector{A}); + + auto backend = runtime::Backend::create("${BACKEND_NAME}"); + + // Create some tensors for input/output + auto a = backend->create_tensor(element::i32, shape); + const vector input{2, 1, 0, -1, -2}; + const vector expected{1, 1, 0, -1, -1}; + copy_data(a, input); + auto result = backend->create_tensor(element::i32, shape); auto handle = backend->compile(f); handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f(input, read_vector(result))); + EXPECT_EQ(expected, read_vector(result)); } From 3de41ec50a5d777fef0bac8464fdffa4d3366598 Mon Sep 17 00:00:00 2001 From: Patryk Elszkowski Date: Tue, 11 May 2021 07:54:19 +0200 Subject: [PATCH 05/99] add zero attribute test for tanh op (#5427) * add zero attribute test for tanh op * apply review suggestion Co-authored-by: Patryk Elszkowski --- ngraph/test/CMakeLists.txt | 1 + ngraph/test/visitors/op/tanh.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 ngraph/test/visitors/op/tanh.cpp diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 6347b884b81..961f9b893a4 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -258,6 +258,7 @@ set(SRC visitors/op/squeeze.cpp visitors/op/sqrt.cpp visitors/op/strided_slice.cpp + visitors/op/tanh.cpp visitors/op/topk.cpp visitors/op/transpose.cpp uint4.cpp diff --git a/ngraph/test/visitors/op/tanh.cpp b/ngraph/test/visitors/op/tanh.cpp new file mode 100644 index 00000000000..ac915bc7025 --- /dev/null +++ b/ngraph/test/visitors/op/tanh.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" + +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset1.hpp" + +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; + +TEST(attributes, tanh_op) +{ + NodeBuilder::get_ops().register_factory(); + const auto data_node = make_shared(element::f32, Shape{1}); + const auto tanh = make_shared(data_node); + + const NodeBuilder builder(tanh); + const auto tanh_attr_number = 0; + + EXPECT_EQ(builder.get_value_map_size(), tanh_attr_number); +} From 1e3b06f439bd9e182461dc860abc3851a57f693a Mon Sep 17 00:00:00 2001 From: Jozef Daniecki Date: Tue, 11 May 2021 08:13:35 +0200 Subject: [PATCH 06/99] Add ngraph visitor tests for Convert operation. (#5533) * Add ngraph visitor tests for Convert operation. * Add attribute count check to Covnert visitor test. --- ngraph/test/CMakeLists.txt | 1 + ngraph/test/visitors/op/convert.cpp | 32 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 ngraph/test/visitors/op/convert.cpp diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 961f9b893a4..703d0ecbe8d 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -213,6 +213,7 @@ set(SRC visitors/op/broadcast.cpp visitors/op/bucketize.cpp visitors/op/constant.cpp + visitors/op/convert.cpp visitors/op/cum_sum.cpp visitors/op/detection_output.cpp visitors/op/elu.cpp diff --git a/ngraph/test/visitors/op/convert.cpp b/ngraph/test/visitors/op/convert.cpp new file mode 100644 index 00000000000..1e384950c5f --- /dev/null +++ b/ngraph/test/visitors/op/convert.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" + +#include "ngraph/ngraph.hpp" +#include "util/visitor.hpp" + +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(attributes, convert_op_v0) +{ + using Convert = op::v0::Convert; + + NodeBuilder::get_ops().register_factory(); + auto data = std::make_shared(element::f32, Shape{2, 4}); + const element::Type destination_type = element::Type_t::i32; + + const auto convert = std::make_shared(data, destination_type); + NodeBuilder builder(convert); + + // attribute count + const auto expected_attr_count = 1; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); + + // destination_type attribute + const auto g_convert = as_type_ptr(builder.create()); + EXPECT_EQ(g_convert->get_destination_type(), convert->get_destination_type()); +} From f824f914a4cd172a62be4822a5e49cc309ade68c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ewa=20Tusie=C5=84?= Date: Tue, 11 May 2021 11:01:27 +0200 Subject: [PATCH 07/99] [ONNX] Add Constant op from opset 13 (#5450) --- .../include/onnx_import/core/node.hpp | 3 + ngraph/frontend/onnx_import/src/core/node.cpp | 26 ++ .../frontend/onnx_import/src/core/tensor.hpp | 25 ++ .../frontend/onnx_import/src/op/constant.cpp | 294 ++++++++++-------- .../frontend/onnx_import/src/op/constant.hpp | 6 + .../frontend/onnx_import/src/ops_bridge.cpp | 1 + .../onnx/constant_bfloat_tensor.prototxt | 44 +++ .../models/onnx/constant_float_array.prototxt | 32 ++ .../onnx/constant_float_scalar.prototxt | 28 ++ .../onnx/constant_float_tensor.prototxt | 44 +++ .../onnx/constant_integer_array.prototxt | 32 ++ .../onnx/constant_integer_scalar.prototxt | 28 ++ ngraph/test/onnx/onnx_import.in.cpp | 61 ++++ ngraph/test/runtime/ie/unit_test.manifest | 4 + 14 files changed, 505 insertions(+), 123 deletions(-) create mode 100644 ngraph/test/models/onnx/constant_bfloat_tensor.prototxt create mode 100644 ngraph/test/models/onnx/constant_float_array.prototxt create mode 100644 ngraph/test/models/onnx/constant_float_scalar.prototxt create mode 100644 ngraph/test/models/onnx/constant_float_tensor.prototxt create mode 100644 ngraph/test/models/onnx/constant_integer_array.prototxt create mode 100644 ngraph/test/models/onnx/constant_integer_scalar.prototxt diff --git a/ngraph/frontend/onnx_import/include/onnx_import/core/node.hpp b/ngraph/frontend/onnx_import/include/onnx_import/core/node.hpp index e5a59fa9ea9..9c4462e6728 100644 --- a/ngraph/frontend/onnx_import/include/onnx_import/core/node.hpp +++ b/ngraph/frontend/onnx_import/include/onnx_import/core/node.hpp @@ -41,6 +41,7 @@ namespace ngraph class Graph; class Subgraph; class Tensor; + class Attribute; class ONNX_IMPORTER_API Node { @@ -59,6 +60,8 @@ namespace ngraph const std::string& domain() const; const std::string& op_type() const; const std::string& get_name() const; + std::vector get_attribute_names() const; + const Attribute& get_attribute(const std::string& name) const; /// \brief Describe the ONNX Node to make debugging graphs easier /// Function will return the Node's name if it has one, or the names of its outputs. diff --git a/ngraph/frontend/onnx_import/src/core/node.cpp b/ngraph/frontend/onnx_import/src/core/node.cpp index 207982ef3b1..4a90d1dbeb7 100644 --- a/ngraph/frontend/onnx_import/src/core/node.cpp +++ b/ngraph/frontend/onnx_import/src/core/node.cpp @@ -207,6 +207,32 @@ namespace ngraph return m_pimpl->has_attribute(name); } + std::vector Node::get_attribute_names() const + { + std::vector attr_names; + const auto& node_attributes = m_pimpl->attributes(); + attr_names.reserve(node_attributes.size()); + std::transform(std::begin(node_attributes), + std::end(node_attributes), + std::back_inserter(attr_names), + [](const Attribute& a) { return a.get_name(); }); + return attr_names; + } + + const Attribute& Node::get_attribute(const std::string& name) const + { + const auto& node_attributes = m_pimpl->attributes(); + auto found_attr = + std::find_if(std::begin(node_attributes), + std::end(node_attributes), + [&name](const Attribute& a) { return a.get_name() == name; }); + if (found_attr == std::end(node_attributes)) + { + throw error::node::UnknownAttribute{this->get_name(), name}; + } + return *found_attr; + } + template <> float Node::get_attribute_value(const std::string& name, float default_value) const { diff --git a/ngraph/frontend/onnx_import/src/core/tensor.hpp b/ngraph/frontend/onnx_import/src/core/tensor.hpp index 53d1dea864c..0c40b77d866 100644 --- a/ngraph/frontend/onnx_import/src/core/tensor.hpp +++ b/ngraph/frontend/onnx_import/src/core/tensor.hpp @@ -248,6 +248,26 @@ namespace ngraph throw error::tensor::invalid_data_type{tensor.data_type()}; } + template <> + inline std::vector + get_data(const ONNX_NAMESPACE::TensorProto& tensor) + { + if (detail::has_tensor_external_data(tensor)) + { + return detail::get_external_data(tensor); + } + if (tensor.has_raw_data()) + { + return detail::__get_raw_data(tensor.raw_data(), + tensor.data_type()); + } + if (tensor.data_type() == ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16) + { + return detail::__get_data(tensor.int32_data()); + } + throw error::tensor::invalid_data_type{tensor.data_type()}; + } + template <> inline std::vector get_data(const ONNX_NAMESPACE::TensorProto& tensor) { @@ -441,6 +461,7 @@ namespace ngraph float64 = ONNX_NAMESPACE::TensorProto_DataType_DOUBLE, uint32 = ONNX_NAMESPACE::TensorProto_DataType_UINT32, uint64 = ONNX_NAMESPACE::TensorProto_DataType_UINT64, + bfloat16 = ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16, complex64 = ONNX_NAMESPACE::TensorProto_DataType_COMPLEX64, complex128 = ONNX_NAMESPACE::TensorProto_DataType_COMPLEX128 }; @@ -526,6 +547,8 @@ namespace ngraph return element::u32; case ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_UINT64: return element::u64; + case ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_BFLOAT16: + return element::bf16; case ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_UNDEFINED: throw error::tensor::data_type_undefined{}; default: throw error::tensor::unsupported_data_type{m_tensor_proto->data_type()}; @@ -561,6 +584,8 @@ namespace ngraph return make_ng_constant(element::u32); case ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_UINT64: return make_ng_constant(element::u64); + case ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_BFLOAT16: + return make_ng_constant(element::bf16); default: throw error::tensor::unsupported_data_type{m_tensor_proto->data_type()}; } } diff --git a/ngraph/frontend/onnx_import/src/op/constant.cpp b/ngraph/frontend/onnx_import/src/op/constant.cpp index 0aa68d8909c..81d0d75d022 100644 --- a/ngraph/frontend/onnx_import/src/op/constant.cpp +++ b/ngraph/frontend/onnx_import/src/op/constant.cpp @@ -3,10 +3,12 @@ // #include "op/constant.hpp" +#include "core/attribute.hpp" #include "core/tensor.hpp" #include "default_opset.hpp" #include "ngraph/log.hpp" #include "ngraph/op/constant.hpp" +#include "ngraph/validation_util.hpp" namespace ngraph { @@ -14,152 +16,159 @@ namespace ngraph { namespace op { - namespace set_1 + namespace { - namespace + template + inline std::shared_ptr + __make_ng_constant(const element::Type& type, const Tensor& tensor) { - template - inline std::shared_ptr - __make_ng_constant(const element::Type& type, const Tensor& tensor) + std::shared_ptr constant{nullptr}; + try { - std::shared_ptr constant{nullptr}; - try - { - constant = std::make_shared( - type, tensor.get_shape(), tensor.get_data()); - } - catch (const ngraph::ngraph_error& exc) - { - NGRAPH_WARN - << "\nCould not create an nGraph Constant for an ONNX Constant " - "node. " - << "Constant with a 0 value was created instead.\n" - << "Verify if the ONNX Constant node contains a correct number of " - "elements matching the node's shape. \n" - << "Detailed error:\n" - << exc.what(); - constant = std::make_shared(type, Shape{}, 0); - } - - return constant; + constant = std::make_shared( + type, tensor.get_shape(), tensor.get_data()); + } + catch (const ngraph::ngraph_error& exc) + { + NGRAPH_WARN + << "\nCould not create an nGraph Constant for an ONNX Constant " + "node. " + << "Constant with a 0 value was created instead.\n" + << "Verify if the ONNX Constant node contains a correct number of " + "elements matching the node's shape. \n" + << "Detailed error:\n" + << exc.what(); + constant = std::make_shared(type, Shape{}, 0); } - template - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - throw error::tensor::unsupported_data_type{tensor}; - } + return constant; + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::f16, tensor); - } + template + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + throw error::tensor::unsupported_data_type{tensor}; + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::f32, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::f16, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::f64, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::f32, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::i8, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::f64, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::i16, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::i8, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::i32, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::i16, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::i64, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::i32, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::u8, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::i64, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::u16, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::u8, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::u32, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::u16, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::u64, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::u32, tensor); + } - template <> - inline std::shared_ptr - make_ng_constant(const Tensor& tensor) - { - return __make_ng_constant(element::boolean, tensor); - } + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::u64, tensor); + } - inline std::shared_ptr - make_constant(const Tensor& tensor) - { + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::boolean, tensor); + } + + template <> + inline std::shared_ptr + make_ng_constant(const Tensor& tensor) + { + return __make_ng_constant(element::bf16, tensor); + } + + inline std::shared_ptr make_constant(const Tensor& tensor) + { #define MAKE_NG_CONSTANT(data_type_) \ case data_type_: return make_ng_constant(tensor) - switch (tensor.get_type()) - { - MAKE_NG_CONSTANT(Tensor::Type::float16); - MAKE_NG_CONSTANT(Tensor::Type::float32); - MAKE_NG_CONSTANT(Tensor::Type::float64); - MAKE_NG_CONSTANT(Tensor::Type::int8); - MAKE_NG_CONSTANT(Tensor::Type::int16); - MAKE_NG_CONSTANT(Tensor::Type::int32); - MAKE_NG_CONSTANT(Tensor::Type::int64); - MAKE_NG_CONSTANT(Tensor::Type::uint8); - MAKE_NG_CONSTANT(Tensor::Type::uint16); - MAKE_NG_CONSTANT(Tensor::Type::uint32); - MAKE_NG_CONSTANT(Tensor::Type::uint64); - MAKE_NG_CONSTANT(Tensor::Type::boolean); - default: throw error::tensor::invalid_data_type{tensor}; - } + switch (tensor.get_type()) + { + MAKE_NG_CONSTANT(Tensor::Type::float16); + MAKE_NG_CONSTANT(Tensor::Type::float32); + MAKE_NG_CONSTANT(Tensor::Type::float64); + MAKE_NG_CONSTANT(Tensor::Type::int8); + MAKE_NG_CONSTANT(Tensor::Type::int16); + MAKE_NG_CONSTANT(Tensor::Type::int32); + MAKE_NG_CONSTANT(Tensor::Type::int64); + MAKE_NG_CONSTANT(Tensor::Type::uint8); + MAKE_NG_CONSTANT(Tensor::Type::uint16); + MAKE_NG_CONSTANT(Tensor::Type::uint32); + MAKE_NG_CONSTANT(Tensor::Type::uint64); + MAKE_NG_CONSTANT(Tensor::Type::boolean); + MAKE_NG_CONSTANT(Tensor::Type::bfloat16); + default: throw error::tensor::invalid_data_type{tensor}; } - } // namespace + } + } // namespace + namespace set_1 + { OutputVector constant(const onnx_import::Node& node) { return {make_constant(node.get_attribute_value("value"))}; @@ -167,6 +176,45 @@ namespace ngraph } // namespace set_1 + namespace set_13 + { + OutputVector constant(const onnx_import::Node& node) + { + auto attributes_names = node.get_attribute_names(); + NGRAPH_CHECK(attributes_names.size() == 1, + "The Constant op expects exactly one attribute." + "Got: ", + attributes_names.size()); + + auto& attribute = node.get_attribute(attributes_names[0]); + + if (attribute.is_float()) + { + return {default_opset::Constant::create( + element::f32, ngraph::Shape{}, {attribute.get_float()})}; + } + else if (attribute.is_float_array()) + { + auto values = attribute.get_float_array(); + return {default_opset::Constant::create( + element::f32, ngraph::Shape{values.size()}, values)}; + } + else if (attribute.is_integer()) + { + return {default_opset::Constant::create( + element::i64, ngraph::Shape{}, {attribute.get_integer()})}; + } + else if (attribute.is_integer_array()) + { + auto values = attribute.get_integer_array(); + return {default_opset::Constant::create( + element::i64, ngraph::Shape{values.size()}, values)}; + } + return {make_constant(node.get_attribute_value(attributes_names[0]))}; + } + + } // namespace set_13 + } // namespace op } // namespace onnx_import diff --git a/ngraph/frontend/onnx_import/src/op/constant.hpp b/ngraph/frontend/onnx_import/src/op/constant.hpp index 530ac440009..43ecb41cf49 100644 --- a/ngraph/frontend/onnx_import/src/op/constant.hpp +++ b/ngraph/frontend/onnx_import/src/op/constant.hpp @@ -19,6 +19,12 @@ namespace ngraph } // namespace set_1 + namespace set_13 + { + OutputVector constant(const Node& node); + + } // namespace set_13 + } // namespace op } // namespace onnx_import diff --git a/ngraph/frontend/onnx_import/src/ops_bridge.cpp b/ngraph/frontend/onnx_import/src/ops_bridge.cpp index 42774e93be2..511c059c61b 100644 --- a/ngraph/frontend/onnx_import/src/ops_bridge.cpp +++ b/ngraph/frontend/onnx_import/src/ops_bridge.cpp @@ -324,6 +324,7 @@ namespace ngraph REGISTER_OPERATOR("Clip", 11, clip); REGISTER_OPERATOR("Concat", 1, concat); REGISTER_OPERATOR("Constant", 1, constant); + REGISTER_OPERATOR("Constant", 13, constant); REGISTER_OPERATOR("ConstantOfShape", 1, constant_of_shape); REGISTER_OPERATOR("Conv", 1, conv); // REGISTER_OPERATOR("ConvInteger", 1, conv_integer); diff --git a/ngraph/test/models/onnx/constant_bfloat_tensor.prototxt b/ngraph/test/models/onnx/constant_bfloat_tensor.prototxt new file mode 100644 index 00000000000..9f7e76623c9 --- /dev/null +++ b/ngraph/test/models/onnx/constant_bfloat_tensor.prototxt @@ -0,0 +1,44 @@ +ir_version: 7 +producer_name: "backend-test" +graph { + node { + output: "values" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 2 + dims: 3 + data_type: 16 + int32_data: 0 + int32_data: 5 + int32_data: 10 + int32_data: 15 + int32_data: 20 + int32_data: 25 + name: "const_tensor" + } + type: TENSOR + } + } + name: "test_constant" + output { + name: "values" + type { + tensor_type { + elem_type: 16 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 3 + } + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/constant_float_array.prototxt b/ngraph/test/models/onnx/constant_float_array.prototxt new file mode 100644 index 00000000000..237fc6e05dc --- /dev/null +++ b/ngraph/test/models/onnx/constant_float_array.prototxt @@ -0,0 +1,32 @@ +ir_version: 7 +producer_name: "backend-test" +graph { + node { + output: "values" + op_type: "Constant" + attribute { + name: "value_floats" + floats: 0.5 + floats: 1.0 + floats: 1.5 + type: FLOATS + } + } + name: "test_constant" + output { + name: "values" + type { + tensor_type { + elem_type: 1 + shape { + dim{ + dim_value: 3 + } + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/constant_float_scalar.prototxt b/ngraph/test/models/onnx/constant_float_scalar.prototxt new file mode 100644 index 00000000000..3a711965bc8 --- /dev/null +++ b/ngraph/test/models/onnx/constant_float_scalar.prototxt @@ -0,0 +1,28 @@ +ir_version: 7 +producer_name: "backend-test" +graph { + node { + output: "values" + op_type: "Constant" + attribute { + name: "value_float" + f: 0.5 + type: FLOAT + } + } + name: "test_constant" + output { + name: "values" + type { + tensor_type { + elem_type: 1 + shape { + + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/constant_float_tensor.prototxt b/ngraph/test/models/onnx/constant_float_tensor.prototxt new file mode 100644 index 00000000000..b37db9d453e --- /dev/null +++ b/ngraph/test/models/onnx/constant_float_tensor.prototxt @@ -0,0 +1,44 @@ +ir_version: 7 +producer_name: "backend-test" +graph { + node { + output: "values" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 2 + dims: 3 + data_type: 1 + float_data: 0 + float_data: 0.5 + float_data: 1.0 + float_data: 1.5 + float_data: 2 + float_data: 2.5 + name: "const_tensor" + } + type: TENSOR + } + } + name: "test_constant" + output { + name: "values" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 3 + } + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/constant_integer_array.prototxt b/ngraph/test/models/onnx/constant_integer_array.prototxt new file mode 100644 index 00000000000..9aaa125ef6b --- /dev/null +++ b/ngraph/test/models/onnx/constant_integer_array.prototxt @@ -0,0 +1,32 @@ +ir_version: 7 +producer_name: "backend-test" +graph { + node { + output: "values" + op_type: "Constant" + attribute { + name: "value_ints" + ints: 0 + ints: 1 + ints: 2 + type: INTS + } + } + name: "test_constant" + output { + name: "values" + type { + tensor_type { + elem_type: 7 + shape { + dim{ + dim_value: 3 + } + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/constant_integer_scalar.prototxt b/ngraph/test/models/onnx/constant_integer_scalar.prototxt new file mode 100644 index 00000000000..2b4f0f3d8b3 --- /dev/null +++ b/ngraph/test/models/onnx/constant_integer_scalar.prototxt @@ -0,0 +1,28 @@ +ir_version: 7 +producer_name: "backend-test" +graph { + node { + output: "values" + op_type: "Constant" + attribute { + name: "value_int" + i: 1 + type: INT + } + } + name: "test_constant" + output { + name: "values" + type { + tensor_type { + elem_type: 7 + shape { + + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/onnx/onnx_import.in.cpp b/ngraph/test/onnx/onnx_import.in.cpp index e0fb314f1e9..bf9551a5cfb 100644 --- a/ngraph/test/onnx/onnx_import.in.cpp +++ b/ngraph/test/onnx/onnx_import.in.cpp @@ -4299,3 +4299,64 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_constant_fill_shape_attribute) test_case.add_expected_output(Shape{2, 3, 4}, std::vector(24, 5)); test_case.run(); } + +NGRAPH_TEST(${BACKEND_NAME}, onnx_constant_float_tensor) +{ + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/constant_float_tensor.prototxt")); + + auto test_case = test::TestCase(function); + test_case.add_expected_output(Shape{2, 3}, {0.0f, 0.5f, 1.f, 1.5f, 2.f, 2.5f}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_constant_bfloat_tensor) +{ + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/constant_bfloat_tensor.prototxt")); + + auto test_case = test::TestCase(function); + test_case.add_expected_output(Shape{2, 3}, {0.f, 5.f, 10.f, 15.f, 20.f, 25.f}); + test_case.run(); +} + + +NGRAPH_TEST(${BACKEND_NAME}, onnx_constant_float_scalar) +{ + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/constant_float_scalar.prototxt")); + + auto test_case = test::TestCase(function); + test_case.add_expected_output(Shape{}, {0.5f}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_constant_float_array) +{ + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/constant_float_array.prototxt")); + + auto test_case = test::TestCase(function); + test_case.add_expected_output(Shape{3}, {0.5f, 1.f, 1.5f}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_constant_integer_scalar) +{ + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/constant_integer_scalar.prototxt")); + + auto test_case = test::TestCase(function); + test_case.add_expected_output(Shape{}, {1}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_constant_integer_array) +{ + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/constant_integer_array.prototxt")); + + auto test_case = test::TestCase(function); + test_case.add_expected_output(Shape{3}, {0, 1, 2}); + test_case.run(); +} diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index 1797f6bfb36..ceeaa049648 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -575,6 +575,10 @@ broadcast_vector_rowwise_int64 broadcast_scalar_to_matrix_int64 abc_int64 +# [NOT_IMPLEMENTED] Output format I64 is not supported yet... +onnx_constant_integer_scalar +onnx_constant_integer_array + # Unsupported primitive of type: SigmoidBackprop sigmoid_bprop_n1c1h4 From a6d8391c4c87959f2d9377e337f160ba7b579e1f Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 11 May 2021 13:05:18 +0300 Subject: [PATCH 08/99] Removed details::no_copy (#5553) --- .../include/details/ie_no_copy.hpp | 50 ------------------- inference-engine/include/ie_iextension.h | 1 - inference-engine/include/ie_imemory_state.hpp | 3 +- .../src/mkldnn_plugin/mkldnn_edge.h | 3 +- .../src/mkldnn_plugin/mkldnn_node.h | 4 +- .../nodes/mkldnn_batch_to_space_node.h | 1 - .../nodes/mkldnn_bin_conv_node.h | 1 - .../nodes/mkldnn_broadcast_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_concat_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_conv_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_convert_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_deconv_node.h | 1 - .../nodes/mkldnn_def_conv_node.h | 1 - .../nodes/mkldnn_depth_to_space_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_eltwise_node.h | 1 - .../mkldnn_embedding_bag_offset_sum_node.h | 1 - .../mkldnn_embedding_bag_packed_sum_node.h | 1 - .../mkldnn_embedding_segments_sum_node.h | 1 - .../nodes/mkldnn_fake_quantize_node.h | 1 - .../nodes/mkldnn_fullyconnected_node.h | 1 - .../nodes/mkldnn_gather_elements_node.h | 1 - .../nodes/mkldnn_gather_nd_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_gather_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_input_node.h | 1 - .../nodes/mkldnn_interpolate_node.h | 1 - .../src/mkldnn_plugin/nodes/mkldnn_lrn_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_matmul_node.h | 1 - .../src/mkldnn_plugin/nodes/mkldnn_mvn_node.h | 1 - .../nodes/mkldnn_normalize_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_one_hot_node.h | 1 - .../src/mkldnn_plugin/nodes/mkldnn_pad_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_pooling_node.h | 1 - .../nodes/mkldnn_psroi_pooling_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_reduce_node.h | 1 - .../nodes/mkldnn_reference_node.h | 1 - .../nodes/mkldnn_region_yolo_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_reorder_node.h | 2 - .../mkldnn_plugin/nodes/mkldnn_reshape_node.h | 1 - .../src/mkldnn_plugin/nodes/mkldnn_rnn.h | 1 - .../nodes/mkldnn_roi_align_node.h | 1 - .../nodes/mkldnn_roi_pooling_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_roll_node.h | 1 - .../nodes/mkldnn_scatter_update_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_select_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_softmax_node.h | 1 - .../nodes/mkldnn_space_to_batch_node.h | 1 - .../nodes/mkldnn_space_to_depth_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_split_node.h | 1 - .../nodes/mkldnn_strided_slice_node.h | 1 - .../nodes/mkldnn_tensoriterator_node.h | 1 - .../mkldnn_plugin/nodes/mkldnn_tile_node.h | 1 - .../nodes/mkldnn_transpose_node.h | 1 - 52 files changed, 4 insertions(+), 105 deletions(-) delete mode 100644 inference-engine/include/details/ie_no_copy.hpp diff --git a/inference-engine/include/details/ie_no_copy.hpp b/inference-engine/include/details/ie_no_copy.hpp deleted file mode 100644 index 5cf967539cf..00000000000 --- a/inference-engine/include/details/ie_no_copy.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -/** - * @brief header file for no_copy class - * - * @file ie_no_copy.hpp - */ -#pragma once - -namespace InferenceEngine { -namespace details { -/** - * @brief This class is used for objects returned from the shared library factory to prevent copying - */ -class no_copy { -protected: - /** - * @brief A default constructor - */ - no_copy() = default; - - /** - * @brief A default destructor - */ - virtual ~no_copy() = default; - - /** - * @brief A removed copy constructor - */ - no_copy(no_copy const&) = delete; - - /** - * @brief A removed assign operator - */ - no_copy& operator=(no_copy const&) = delete; - - /** - * @brief A removed move constructor - */ - no_copy(no_copy&&) = delete; - - /** - * @brief A removed move operator - */ - no_copy& operator=(no_copy&&) = delete; -}; -} // namespace details -} // namespace InferenceEngine diff --git a/inference-engine/include/ie_iextension.h b/inference-engine/include/ie_iextension.h index 2010bca1644..7a033b95aaf 100644 --- a/inference-engine/include/ie_iextension.h +++ b/inference-engine/include/ie_iextension.h @@ -19,7 +19,6 @@ #include "ie_layouts.h" #include "ie_blob.h" #include "ie_version.hpp" -#include "details/ie_no_copy.hpp" /** * @def INFERENCE_EXTENSION_API(TYPE) diff --git a/inference-engine/include/ie_imemory_state.hpp b/inference-engine/include/ie_imemory_state.hpp index fdac3c7ebbb..729d86f721a 100644 --- a/inference-engine/include/ie_imemory_state.hpp +++ b/inference-engine/include/ie_imemory_state.hpp @@ -14,7 +14,6 @@ #include "ie_blob.h" #include "ie_common.h" -#include "details/ie_no_copy.hpp" namespace InferenceEngine { @@ -23,7 +22,7 @@ namespace InferenceEngine { * @interface IVariableState * @brief Manages data for reset operations */ -class IVariableState : public details::no_copy { +class IVariableState { public: IE_SUPPRESS_DEPRECATED_START /** diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_edge.h b/inference-engine/src/mkldnn_plugin/mkldnn_edge.h index 9a092fe7da6..9ea831a5725 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_edge.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_edge.h @@ -6,7 +6,6 @@ #include #include -#include
#include "mkldnn_memory.h" #include "mkldnn_dims.h" #include "mkldnn_weights_cache.hpp" @@ -24,7 +23,7 @@ class MKLDNNEdge; using MKLDNNEdgePtr = std::shared_ptr; using MKLDNNEdgeWeakPtr = std::weak_ptr; -class MKLDNNEdge : public InferenceEngine::details::no_copy { +class MKLDNNEdge { public: MKLDNNEdge(const std::shared_ptr& parent, const std::shared_ptr& child, diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_node.h b/inference-engine/src/mkldnn_plugin/mkldnn_node.h index 5653bb36c91..2a0102cccde 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_node.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_node.h @@ -288,7 +288,7 @@ private: } }; -class MKLDNNNode : public InferenceEngine::details::no_copy { +class MKLDNNNode { public: template struct Tag {}; @@ -326,7 +326,7 @@ public: class NodesFactory; static NodesFactory & factory(); - ~MKLDNNNode() override = default; + virtual ~MKLDNNNode() = default; void addEdge(const MKLDNNEdgeWeakPtr& edge); void removeEdge(const MKLDNNEdgeWeakPtr& edge); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.h index a7044d13218..cab89df7dc6 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNBatchToSpaceNode : public MKLDNNNode { public: MKLDNNBatchToSpaceNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNBatchToSpaceNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_bin_conv_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_bin_conv_node.h index b8a93caf4c5..f67070f8440 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_bin_conv_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_bin_conv_node.h @@ -75,7 +75,6 @@ struct jit_uni_bin_conv_kernel { class MKLDNNBinaryConvolutionNode : public MKLDNNNode { public: MKLDNNBinaryConvolutionNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNBinaryConvolutionNode() override = default; void getSupportedDescriptors() override; void createPrimitive() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_broadcast_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_broadcast_node.h index e9d9315b033..0d86a2a99ef 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_broadcast_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_broadcast_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNBroadcastNode : public MKLDNNNode { public: MKLDNNBroadcastNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNBroadcastNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.h index ffb8ce22feb..234eeb4e531 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.h @@ -14,7 +14,6 @@ namespace MKLDNNPlugin { class MKLDNNConcatNode : public MKLDNNNode { public: MKLDNNConcatNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNConcatNode() override = default; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h index 10c4755230a..1cdc0065c4c 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h @@ -17,7 +17,6 @@ class MKLDNNEltwiseNode; class MKLDNNConvolutionNode : public MKLDNNNode { public: MKLDNNConvolutionNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNConvolutionNode() override = default; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_convert_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_convert_node.h index 6aacf7f1e5a..ca43bb3db5c 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_convert_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_convert_node.h @@ -16,7 +16,6 @@ public: MKLDNNConvertNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); MKLDNNConvertNode(const InferenceEngine::SizeVector &dims, const InferenceEngine::Precision &inPrc, const InferenceEngine::Precision &outPrc, const std::string &nodeName, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNConvertNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_deconv_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_deconv_node.h index f5715ea6368..a9c17ee4c25 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_deconv_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_deconv_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNDeconvolutionNode : public MKLDNNNode { public: MKLDNNDeconvolutionNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNDeconvolutionNode() override = default; void getSupportedDescriptors() override; void createDescriptor(const std::vector& inputDesc, diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_def_conv_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_def_conv_node.h index 2c9a77a8c96..e74e49788cc 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_def_conv_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_def_conv_node.h @@ -65,7 +65,6 @@ struct jit_uni_def_conv_kernel { class MKLDNNDeformableConvolutionNode : public MKLDNNNode { public: MKLDNNDeformableConvolutionNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNDeformableConvolutionNode() override = default; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.h index 140c290e3a7..a7c0145fc81 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.h @@ -14,7 +14,6 @@ namespace MKLDNNPlugin { class MKLDNNDepthToSpaceNode : public MKLDNNNode { public: MKLDNNDepthToSpaceNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNDepthToSpaceNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.h index 8ae34000430..c6e77d9c20e 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.h @@ -60,7 +60,6 @@ struct jit_uni_eltwise_kernel { class MKLDNNEltwiseNode : public MKLDNNNode { public: MKLDNNEltwiseNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNEltwiseNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_bag_offset_sum_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_bag_offset_sum_node.h index 4ae3d331822..26a38b05081 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_bag_offset_sum_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_bag_offset_sum_node.h @@ -16,7 +16,6 @@ namespace MKLDNNPlugin { class MKLDNNEmbeddingBagOffsetSumNode : public MKLDNNNode, public MKLDNNEmbeddingBagSumNode { public: MKLDNNEmbeddingBagOffsetSumNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNEmbeddingBagOffsetSumNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_bag_packed_sum_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_bag_packed_sum_node.h index c83d4fdef0c..9d67116a499 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_bag_packed_sum_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_bag_packed_sum_node.h @@ -16,7 +16,6 @@ namespace MKLDNNPlugin { class MKLDNNEmbeddingBagPackedSumNode : public MKLDNNNode, public MKLDNNEmbeddingBagSumNode { public: MKLDNNEmbeddingBagPackedSumNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNEmbeddingBagPackedSumNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_segments_sum_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_segments_sum_node.h index 54e269a391e..b20e9d67650 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_segments_sum_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_embedding_segments_sum_node.h @@ -16,7 +16,6 @@ namespace MKLDNNPlugin { class MKLDNNEmbeddingSegmentsSumNode : public MKLDNNNode, public MKLDNNEmbeddingBagSumNode { public: MKLDNNEmbeddingSegmentsSumNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNEmbeddingSegmentsSumNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fake_quantize_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fake_quantize_node.h index 99ac82a50e6..4430acac9ba 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fake_quantize_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fake_quantize_node.h @@ -65,7 +65,6 @@ struct jit_uni_quantize_kernel { class MKLDNNFakeQuantizeNode : public MKLDNNNode { public: MKLDNNFakeQuantizeNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNFakeQuantizeNode() override = default; void initSupportedPrimitiveDescriptors() override; void getSupportedDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fullyconnected_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fullyconnected_node.h index 4b5622a8cda..63b1e88ae6f 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fullyconnected_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fullyconnected_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNFullyConnectedNode : public MKLDNNNode { public: MKLDNNFullyConnectedNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNFullyConnectedNode() override = default; std::vector getAvailableFormatsForDims(const MKLDNNDims &dims) const override; void getSupportedDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_elements_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_elements_node.h index 51c49473c13..30d1fda9e95 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_elements_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_elements_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNGatherElementsNode : public MKLDNNNode { public: MKLDNNGatherElementsNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNGatherElementsNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.h index 253710333c1..3845fabaf70 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNGatherNDNode : public MKLDNNNode { public: MKLDNNGatherNDNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNGatherNDNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_node.h index 96ed3846d8b..4631436f3c6 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNGatherNode : public MKLDNNNode { public: MKLDNNGatherNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNGatherNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_input_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_input_node.h index fa1cc0c49c3..d6b984c0c3f 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_input_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_input_node.h @@ -15,7 +15,6 @@ public: MKLDNNInputNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); MKLDNNInputNode(const InferenceEngine::SizeVector &dims, const InferenceEngine::Precision &prc, const std::string &name, const std::string &type, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNInputNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_interpolate_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_interpolate_node.h index 5912ddaa5e8..2b2f1c38d90 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_interpolate_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_interpolate_node.h @@ -91,7 +91,6 @@ struct jit_uni_interpolate_kernel { class MKLDNNInterpolateNode : public MKLDNNNode { public: MKLDNNInterpolateNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNInterpolateNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_lrn_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_lrn_node.h index 461eddfead8..53cfaa79682 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_lrn_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_lrn_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNLrnNode : public MKLDNNNode { public: MKLDNNLrnNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNLrnNode() override = default; void getSupportedDescriptors() override; void createDescriptor(const std::vector& inputDesc, diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_matmul_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_matmul_node.h index 71fbacd6e47..6196665aabc 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_matmul_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_matmul_node.h @@ -14,7 +14,6 @@ namespace MKLDNNPlugin { class MKLDNNMatMulNode : public MKLDNNNode { public: MKLDNNMatMulNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNMatMulNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h index c23da5e0c11..af282cc3d8a 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h @@ -73,7 +73,6 @@ struct jit_uni_mvn_kernel { class MKLDNNMVNNode : public MKLDNNNode { public: MKLDNNMVNNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNMVNNode() override = default; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_normalize_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_normalize_node.h index 7e99d063a3f..bcb7b0d8d49 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_normalize_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_normalize_node.h @@ -74,7 +74,6 @@ struct jit_uni_normalize_kernel { class MKLDNNNormalizeL2Node : public MKLDNNNode { public: MKLDNNNormalizeL2Node(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNNormalizeL2Node() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_one_hot_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_one_hot_node.h index ee355ce26a3..9f39ff1232e 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_one_hot_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_one_hot_node.h @@ -16,7 +16,6 @@ namespace MKLDNNPlugin { class MKLDNNOneHotNode : public MKLDNNNode { public: MKLDNNOneHotNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNOneHotNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.h index 8be96b2bea6..a4a1333914b 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.h @@ -13,7 +13,6 @@ namespace MKLDNNPlugin { class MKLDNNPadNode : public MKLDNNNode { public: MKLDNNPadNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNPadNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.h index 5cb524fa817..1f6acf58b78 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNPoolingNode : public MKLDNNNode { public: MKLDNNPoolingNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNPoolingNode() override = default; void createDescriptor(const std::vector& inputDesc, const std::vector& outputDesc) override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_psroi_pooling_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_psroi_pooling_node.h index dc668681e97..24e015d3a6d 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_psroi_pooling_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_psroi_pooling_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNPSROIPoolingNode : public MKLDNNNode { public: MKLDNNPSROIPoolingNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNPSROIPoolingNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.h index f0e386567c2..07e2724d98a 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.h @@ -65,7 +65,6 @@ struct jit_uni_reduce_post_kernel { class MKLDNNReduceNode : public MKLDNNNode { public: MKLDNNReduceNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNReduceNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.h index ed78ffe14bd..ce27028aa56 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.h @@ -13,7 +13,6 @@ namespace MKLDNNPlugin { class MKLDNNReferenceNode : public MKLDNNNode { public: MKLDNNReferenceNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache, const std::string& errorMessage); - ~MKLDNNReferenceNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_region_yolo_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_region_yolo_node.h index c4c4f525e80..31404a5be11 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_region_yolo_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_region_yolo_node.h @@ -40,7 +40,6 @@ struct jit_uni_logistic_kernel { class MKLDNNRegionYoloNode : public MKLDNNNode { public: MKLDNNRegionYoloNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNRegionYoloNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reorder_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reorder_node.h index 85112c36875..eea18de13b6 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reorder_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reorder_node.h @@ -18,8 +18,6 @@ public: MKLDNNReorderNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); MKLDNNReorderNode(const std::string& name, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNReorderNode() override = default; - void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; void createPrimitive() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.h index 12f7009b453..fcd44b3ba03 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNReshapeNode : public MKLDNNNode { public: MKLDNNReshapeNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNReshapeNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.h index 2551dd86976..7b42760a425 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.h @@ -14,7 +14,6 @@ namespace MKLDNNPlugin { class MKLDNNRNN : public MKLDNNNode { public: MKLDNNRNN(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNRNN() override = default; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.h index 24831cce5b4..9f3d31c4783 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.h @@ -16,7 +16,6 @@ namespace MKLDNNPlugin { class MKLDNNROIAlignNode : public MKLDNNNode { public: MKLDNNROIAlignNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNROIAlignNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_pooling_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_pooling_node.h index c9e2be59924..d796fd47a78 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_pooling_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_pooling_node.h @@ -61,7 +61,6 @@ struct jit_uni_roi_pooling_kernel { class MKLDNNROIPoolingNode : public MKLDNNNode { public: MKLDNNROIPoolingNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNROIPoolingNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roll_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roll_node.h index 102b55c5e63..c8118caa153 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roll_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roll_node.h @@ -13,7 +13,6 @@ namespace MKLDNNPlugin { class MKLDNNRollNode : public MKLDNNNode { public: MKLDNNRollNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNRollNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_scatter_update_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_scatter_update_node.h index c3656209b96..41519bc6346 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_scatter_update_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_scatter_update_node.h @@ -21,7 +21,6 @@ enum class ScatterUpdateMode { class MKLDNNScatterUpdateNode : public MKLDNNNode { public: MKLDNNScatterUpdateNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNScatterUpdateNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_select_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_select_node.h index 810b25c5333..1fc6adebb60 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_select_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_select_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNSelectNode : public MKLDNNNode { public: MKLDNNSelectNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNSelectNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_softmax_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_softmax_node.h index 58ec5904452..b422eb3f030 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_softmax_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_softmax_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNSoftMaxNode : public MKLDNNNode { public: MKLDNNSoftMaxNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNSoftMaxNode() override = default; void initOptimalPrimitiveDescriptor() override; void createDescriptor(const std::vector& inputDesc, diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_batch_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_batch_node.h index 58b2b8661de..f5c9fd1ec9d 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_batch_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_batch_node.h @@ -15,7 +15,6 @@ namespace MKLDNNPlugin { class MKLDNNSpaceToBatchNode : public MKLDNNNode { public: MKLDNNSpaceToBatchNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNSpaceToBatchNode() override = default; void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.h index 7fa7b224201..b7639b90a18 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.h @@ -14,7 +14,6 @@ namespace MKLDNNPlugin { class MKLDNNSpaceToDepthNode : public MKLDNNNode { public: MKLDNNSpaceToDepthNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNSpaceToDepthNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.h index ea9c1efcc35..8428e20a9fd 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.h @@ -13,7 +13,6 @@ namespace MKLDNNPlugin { class MKLDNNSplitNode : public MKLDNNNode { public: MKLDNNSplitNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNSplitNode() override = default; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_strided_slice_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_strided_slice_node.h index 33da479d30a..91bf6701877 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_strided_slice_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_strided_slice_node.h @@ -14,7 +14,6 @@ namespace MKLDNNPlugin { class MKLDNNStridedSliceNode : public MKLDNNNode { public: MKLDNNStridedSliceNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNStridedSliceNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_tensoriterator_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_tensoriterator_node.h index 3f3dd96e6f1..32e5eac70b2 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_tensoriterator_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_tensoriterator_node.h @@ -58,7 +58,6 @@ protected: class MKLDNNTensorIteratorNode : public MKLDNNNode { public: MKLDNNTensorIteratorNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNTensorIteratorNode() override = default; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_tile_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_tile_node.h index b414f9be7ce..a6fd6e51168 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_tile_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_tile_node.h @@ -13,7 +13,6 @@ namespace MKLDNNPlugin { class MKLDNNTileNode : public MKLDNNNode { public: MKLDNNTileNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNTileNode() override = default; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_transpose_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_transpose_node.h index f1d291bc8a4..7ba21e5ba82 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_transpose_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_transpose_node.h @@ -18,7 +18,6 @@ namespace MKLDNNPlugin { class MKLDNNTransposeNode : public MKLDNNNode { public: MKLDNNTransposeNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); - ~MKLDNNTransposeNode() override = default; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; From d11c5e4c9daf3c5faab85de6210ffe1a8b2a47be Mon Sep 17 00:00:00 2001 From: Maksim Proshin Date: Tue, 11 May 2021 14:35:33 +0300 Subject: [PATCH 09/99] Moving POT to Optimization section in index.md and replacing Toolkit by Tool in a few places (#4272) * Update get_started_dl_workbench.md POToolkit => POTool * Update QuantizedNetworks.md POToolkit => POTool * Moving POT to optimizations section Moving POT to optimizations section --- docs/IE_PLUGIN_DG/QuantizedNetworks.md | 2 +- docs/get_started/get_started_dl_workbench.md | 4 ++-- docs/index.md | 11 +++++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/IE_PLUGIN_DG/QuantizedNetworks.md b/docs/IE_PLUGIN_DG/QuantizedNetworks.md index c327c3775fb..bbb5a508550 100644 --- a/docs/IE_PLUGIN_DG/QuantizedNetworks.md +++ b/docs/IE_PLUGIN_DG/QuantizedNetworks.md @@ -35,7 +35,7 @@ Thus we can define: **Note**: During the quantization process the values `input_low`, `input_high`, `output_low`, `output_high` are selected so that to map a floating-point zero exactly to an integer value (zero-point) and vice versa. ## Quantization specifics and restrictions -In general, OpenVINO can represent and execute quantized models from different sources. However, the Post-training Optimization Toolkit (POT) +In general, OpenVINO can represent and execute quantized models from different sources. However, the Post-training Optimization Tool (POT) is considered the default way to get optimized models. Since the POT supports HW-aware quantization it means that specific rules can be implemented in it for the particular HW. However, it is reasonable to have compatibility with general-purpose HW such as CPU and GPU and support their quantization schemes. Below we define these rules as follows: diff --git a/docs/get_started/get_started_dl_workbench.md b/docs/get_started/get_started_dl_workbench.md index 701f23f66d6..edd1ab21cd6 100644 --- a/docs/get_started/get_started_dl_workbench.md +++ b/docs/get_started/get_started_dl_workbench.md @@ -13,7 +13,7 @@ OpenVINO™ toolkit components: with pre-trained models for a range of different tasks * [Model Optimizer](../MO_DG/Deep_Learning_Model_Optimizer_DevGuide.md) to transform models into the Intermediate Representation (IR) format -* [Post-Training Optimization toolkit](@ref pot_README) to calibrate a model and then execute it in the +* [Post-training Optimization Tool](@ref pot_README) to calibrate a model and then execute it in the INT8 precision * [Accuracy Checker](@ref omz_tools_accuracy_checker) to determine the accuracy of a model * [Benchmark Tool](@ref openvino_inference_engine_samples_benchmark_app_README) to estimate inference performance on supported devices @@ -136,4 +136,4 @@ For detailed instructions to create a new project, visit the links below: * [Inference Engine Developer Guide](../IE_DG/Deep_Learning_Inference_Engine_DevGuide.md) * [Model Optimizer Developer Guide](../MO_DG/Deep_Learning_Model_Optimizer_DevGuide.md) * [Inference Engine Samples Overview](../IE_DG/Samples_Overview.md) -* [Overview of OpenVINO™ Toolkit Pre-Trained Models](https://software.intel.com/en-us/openvino-toolkit/documentation/pretrained-models) \ No newline at end of file +* [Overview of OpenVINO™ Toolkit Pre-Trained Models](https://software.intel.com/en-us/openvino-toolkit/documentation/pretrained-models) diff --git a/docs/index.md b/docs/index.md index 15d0c2a3a2b..ca6a1fa6b2e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,11 +29,14 @@ If your neural network model contains layers that are not in the list of known l Run the [Accuracy Checker utility](@ref omz_tools_accuracy_checker) either against source topologies or against the output representation to evaluate the accuracy of inference. The Accuracy Checker is also part of the [Deep Learning Workbench](@ref workbench_docs_Workbench_DG_Introduction), an integrated web-based performance analysis studio. +Use the [Post-training Optimization Tool](@ref pot_README) to accelerate the inference of a deep learning model by quantizing it to INT8. + Useful documents for model optimization: * [Model Optimizer Developer Guide](MO_DG/Deep_Learning_Model_Optimizer_DevGuide.md) * [Intermediate Representation and Opsets](MO_DG/IR_and_opsets.md) * [Custom Layers Guide](HOWTO/Custom_Layers_Guide.md) * [Accuracy Checker utility](@ref omz_tools_accuracy_checker) +* [Post-training Optimization Tool](@ref pot_README) * [Deep Learning Workbench](@ref workbench_docs_Workbench_DG_Introduction) * [Model Downloader](@ref omz_tools_downloader) utility * [Intel's Pretrained Models (Open Model Zoo)](@ref omz_models_group_intel) @@ -42,7 +45,7 @@ Useful documents for model optimization: ### Running and Tuning Inference The other core component of OpenVINO™ is the [Inference Engine](IE_DG/Deep_Learning_Inference_Engine_DevGuide.md), which manages the loading and compiling of the optimized neural network model, runs inference operations on input data, and outputs the results. Inference Engine can execute synchronously or asynchronously, and its plugin architecture manages the appropriate compilations for execution on multiple Intel® devices, including both workhorse CPUs and specialized graphics and video processing platforms (see below, Packaging and Deployment). -You can use OpenVINO™ Tuning Utilities with the Inference Engine to trial and test inference on your model. The Benchmark utility uses an input model to run iterative tests for throughput or latency measures, and the [Cross Check Utility](../inference-engine/tools/cross_check_tool/README.md) compares performance of differently configured inferences. The [Post-Training Optimization Tool](@ref pot_README) integrates a suite of quantization- and calibration-based tools to further streamline performance. +You can use OpenVINO™ Tuning Utilities with the Inference Engine to trial and test inference on your model. The Benchmark utility uses an input model to run iterative tests for throughput or latency measures, and the [Cross Check Utility](../inference-engine/tools/cross_check_tool/README.md) compares performance of differently configured inferences. For a full browser-based studio integrating these other key tuning utilities, try the [Deep Learning Workbench](@ref workbench_docs_Workbench_DG_Introduction). ![](img/OV-diagram-step3.png) @@ -56,7 +59,7 @@ Useful documents for inference tuning: * [Inference Engine API References](./api_references.html) * [Inference Code Samples](IE_DG/Samples_Overview.md) * [Application Demos](@ref omz_demos) -* [Post-Training Optimization Tool Guide](@ref pot_README) +* [Low Precision Optimization Guide] (@ref pot_docs_LowPrecisionOptimizationGuide) * [Deep Learning Workbench Guide](@ref workbench_docs_Workbench_DG_Introduction) * [Intel Media SDK](https://github.com/Intel-Media-SDK/MediaSDK) * [DL Streamer Samples](@ref gst_samples_README) @@ -86,7 +89,7 @@ Intel® Distribution of OpenVINO™ toolkit includes the following components: - [Deep Learning Inference Engine](IE_DG/Deep_Learning_Inference_Engine_DevGuide.md): A unified API to allow high performance inference on many hardware types including Intel® CPU, Intel® Integrated Graphics, Intel® Neural Compute Stick 2, Intel® Vision Accelerator Design with Intel® Movidius™ vision processing unit (VPU). - [Inference Engine Samples](IE_DG/Samples_Overview.md): A set of simple console applications demonstrating how to use the Inference Engine in your applications. - [Deep Learning Workbench](@ref workbench_docs_Workbench_DG_Introduction): A web-based graphical environment that allows you to easily use various sophisticated OpenVINO™ toolkit components. -- [Post-Training Optimization tool](@ref pot_README): A tool to calibrate a model and then execute it in the INT8 precision. +- [Post-training Optimization Tool](@ref pot_README): A tool to calibrate a model and then execute it in the INT8 precision. - Additional Tools: A set of tools to work with your models including [Benchmark App](../inference-engine/tools/benchmark_tool/README.md), [Cross Check Tool](../inference-engine/tools/cross_check_tool/README.md), [Compile tool](../inference-engine/tools/compile_tool/README.md). - [Open Model Zoo](@ref omz_models_group_intel) - [Demos](@ref omz_demos): Console applications that provide robust application templates to help you implement specific deep learning scenarios. @@ -100,4 +103,4 @@ Intel® Distribution of OpenVINO™ toolkit includes the following components: - [OpenCV](https://docs.opencv.org/master/) : OpenCV* community version compiled for Intel® hardware - [Intel® Media SDK](https://software.intel.com/en-us/media-sdk) (in Intel® Distribution of OpenVINO™ toolkit for Linux only) -OpenVINO™ Toolkit opensource version is available on [GitHub](https://github.com/openvinotoolkit/openvino). For building the Inference Engine from the source code, see the build instructions. \ No newline at end of file +OpenVINO™ Toolkit opensource version is available on [GitHub](https://github.com/openvinotoolkit/openvino). For building the Inference Engine from the source code, see the build instructions. From 42226fccae7c9a4e2009290343eccc719752580d Mon Sep 17 00:00:00 2001 From: Anastasia Kazantaeva Date: Tue, 11 May 2021 15:58:32 +0300 Subject: [PATCH 10/99] Upgrade message for 2021.4 lts (#5471) --- model-optimizer/mo/utils/get_ov_update_message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model-optimizer/mo/utils/get_ov_update_message.py b/model-optimizer/mo/utils/get_ov_update_message.py index ca8d1dfb3b1..67a7bd86a04 100644 --- a/model-optimizer/mo/utils/get_ov_update_message.py +++ b/model-optimizer/mo/utils/get_ov_update_message.py @@ -8,9 +8,9 @@ msg_fmt = 'It\'s been a while, check for a new version of ' + \ def get_ov_update_message(): - expected_update_date = datetime.date(year=2021, month=7, day=1) + expected_update_date = datetime.date(year=2021, month=12, day=15) current_date = datetime.date.today() - link = 'https://software.intel.com/content/www/us/en/develop/tools/openvino-toolkit/download.html?cid=other&source=prod&campid=ww_2021_bu_IOTG_OpenVINO-2021-3&content=upg_all&medium=organic' + link = 'https://software.intel.com/content/www/us/en/develop/tools/openvino-toolkit/download.html?cid=other&source=prod&campid=ww_2021_bu_IOTG_OpenVINO-2021-4-LTS&content=upg_all&medium=organic' return msg_fmt.format(link) if current_date >= expected_update_date else None From 0dc161ad8257adc07c2d002a32b9fe2dc5330d3b Mon Sep 17 00:00:00 2001 From: Vladimir Paramuzov Date: Tue, 11 May 2021 16:55:33 +0300 Subject: [PATCH 11/99] [IE CLDNN] Added CACHE_DIR option into docs (#5592) --- docs/IE_DG/supported_plugins/CL_DNN.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/IE_DG/supported_plugins/CL_DNN.md b/docs/IE_DG/supported_plugins/CL_DNN.md index a8cfbc57912..ea32d2d8cee 100644 --- a/docs/IE_DG/supported_plugins/CL_DNN.md +++ b/docs/IE_DG/supported_plugins/CL_DNN.md @@ -16,7 +16,7 @@ For demonstration purposes, see the [Hello Query Device C++ Sample](../../../inf ```sh ./hello_query_device -Available devices: +Available devices: Device: CPU ... Device: GPU.0 @@ -24,7 +24,7 @@ Available devices: Device: GPU.1 ... Device: HDDL -``` +``` ## Optimizations @@ -41,31 +41,31 @@ Merge of a Convolution layer and any of the simple layers listed below: > **NOTE**: You can have any number and order of simple layers. -A combination of a Convolution layer and simple layers results in a single fused layer called -*Convolution*: +A combination of a Convolution layer and simple layers results in a single fused layer called +*Convolution*: ![conv_simple_01] ### Fusing Pooling and FakeQuantize Layers -A combination of Pooling and FakeQuantize layers results in a single fused layer called *Pooling*: +A combination of Pooling and FakeQuantize layers results in a single fused layer called *Pooling*: ![pooling_fakequant_01] ### Fusing Activation Layers Given the linear pattern, an Activation layer can be fused into other layers: - + ![fullyconnected_activation_01] ### Fusing Convolution and Sum Layers -A combination of Convolution, Simple, and Eltwise layers with the sum operation results in a single layer called *Convolution*: +A combination of Convolution, Simple, and Eltwise layers with the sum operation results in a single layer called *Convolution*: ![conv_sum_relu_01] ### Fusing a Group of Convolutions -If a topology contains the following pipeline, a GPU plugin merges Split, Convolution, and Concatenation layers into a single Convolution layer with the group parameter: +If a topology contains the following pipeline, a GPU plugin merges Split, Convolution, and Concatenation layers into a single Convolution layer with the group parameter: > **NOTE**: Parameters of the Convolution layers must coincide. ![group_convolutions_01] @@ -104,6 +104,7 @@ When specifying key values as raw strings (that is, when using Python API), omit | Parameter Name | Parameter Values | Default | Description | |---------------------|-----------------------------|-----------------|-----------------------------------------------------------| +| `KEY_CACHE_DIR` | `""` | `""` | Specifies a directory where compiled OCL binaries can be cached. First model loading generates the cache, and all subsequent LoadNetwork calls use precompiled kernels which significantly improves load time. If empty - caching is disabled | | `KEY_PERF_COUNT` | `YES` / `NO` | `NO` | Collect performance counters during inference | | `KEY_CONFIG_FILE` | `" [ ...]"` | `""` | Load custom layer configuration files | | `KEY_DUMP_KERNELS` | `YES` / `NO` | `NO` | Dump the final kernels used for custom layers | From 9db7f849df7d9d2ad774bbca2375ff71eb088ff3 Mon Sep 17 00:00:00 2001 From: Anton Pankratv Date: Tue, 11 May 2021 20:02:00 +0300 Subject: [PATCH 12/99] Fixed return warnings (#5410) --- inference-engine/include/cpp/ie_infer_request.hpp | 2 +- .../src/inference_engine/cpp/ie_executable_network.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/inference-engine/include/cpp/ie_infer_request.hpp b/inference-engine/include/cpp/ie_infer_request.hpp index fd70469ad5f..4ca0e59335d 100644 --- a/inference-engine/include/cpp/ie_infer_request.hpp +++ b/inference-engine/include/cpp/ie_infer_request.hpp @@ -191,7 +191,7 @@ public: */ template void SetCompletionCallback(F callbackToSet) { - return SetCallback{*this}(std::move(callbackToSet)); + SetCallback{*this}(std::move(callbackToSet)); } /** diff --git a/inference-engine/src/inference_engine/cpp/ie_executable_network.cpp b/inference-engine/src/inference_engine/cpp/ie_executable_network.cpp index d282f4c88c5..cef73ed9347 100644 --- a/inference-engine/src/inference_engine/cpp/ie_executable_network.cpp +++ b/inference-engine/src/inference_engine/cpp/ie_executable_network.cpp @@ -74,11 +74,11 @@ InferRequest::Ptr ExecutableNetwork::CreateInferRequestPtr() { } void ExecutableNetwork::Export(const std::string& modelFileName) { - EXEC_NET_CALL_STATEMENT(return _impl->Export(modelFileName)); + EXEC_NET_CALL_STATEMENT(_impl->Export(modelFileName)); } void ExecutableNetwork::Export(std::ostream& networkModel) { - EXEC_NET_CALL_STATEMENT(return _impl->Export(networkModel)); + EXEC_NET_CALL_STATEMENT(_impl->Export(networkModel)); } CNNNetwork ExecutableNetwork::GetExecGraphInfo() { From dc22c177d56522bc906d3d1ebeaef15d07421dc8 Mon Sep 17 00:00:00 2001 From: Roman Kazantsev Date: Tue, 11 May 2021 21:36:04 +0300 Subject: [PATCH 13/99] Extend MO for operation Einsum-7 (#5401) * Extend MO for operation Einsum-7 Signed-off-by: Roman Kazantsev * Add extractor for einsum and optimize code based on review feedback Signed-off-by: Roman Kazantsev * Fix the code based on the review: correct code, tests and comments; move insert_transpose Signed-off-by: Roman Kazantsev * Fix LayoutChangeForEinsum transformation condition Signed-off-by: Roman Kazantsev * Update third-party dependencies Signed-off-by: Roman Kazantsev --- model-optimizer/automation/package_BOM.txt | 6 + .../extensions/back/LayoutChangeForEinsum.py | 57 +++++ .../extensions/front/mxnet/einsum_ext.py | 20 ++ .../extensions/front/onnx/einsum_ext.py | 19 ++ .../extensions/front/tf/einsum_ext.py | 18 ++ model-optimizer/extensions/ops/einsum.py | 232 ++++++++++++++++++ .../ir_reader/extenders/einsum_extender.py | 17 ++ .../back/LayoutChangeForEinsum_test.py | 82 +++++++ .../unit_tests/extensions/ops/einsum_test.py | 90 +++++++ .../extensions/ops/gathernd_test.py | 4 +- 10 files changed, 543 insertions(+), 2 deletions(-) create mode 100644 model-optimizer/extensions/back/LayoutChangeForEinsum.py create mode 100644 model-optimizer/extensions/front/mxnet/einsum_ext.py create mode 100644 model-optimizer/extensions/front/onnx/einsum_ext.py create mode 100644 model-optimizer/extensions/front/tf/einsum_ext.py create mode 100644 model-optimizer/extensions/ops/einsum.py create mode 100644 model-optimizer/mo/utils/ir_reader/extenders/einsum_extender.py create mode 100644 model-optimizer/unit_tests/extensions/back/LayoutChangeForEinsum_test.py create mode 100644 model-optimizer/unit_tests/extensions/ops/einsum_test.py diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index d8b90b715a4..d236df8f3d2 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -29,6 +29,7 @@ extensions/back/GroupedConvWeightsNormalize.py extensions/back/insert_compatibility_l2normalization.py extensions/back/InterpolateReshape.py extensions/back/kaldi_remove_memory_output.py +extensions/back/LayoutChangeForEinsum.py extensions/back/LayoutChangeForGatherND.py extensions/back/LeakyReLUMutation.py extensions/back/LinearToLinearONNXReplacer.py @@ -193,6 +194,7 @@ extensions/front/mxnet/custom_rpn_proposal.py extensions/front/mxnet/deformable_conv_ext.py extensions/front/mxnet/deformable_psroi_pooling_ext.py extensions/front/mxnet/dropout_ext.py +extensions/front/mxnet/einsum_ext.py extensions/front/mxnet/elementwise_ext.py extensions/front/mxnet/eltwise_scalar_replacers.py extensions/front/mxnet/exp_ext.py @@ -278,6 +280,7 @@ extensions/front/onnx/dequantize_linear_resolver.py extensions/front/onnx/detection_output.py extensions/front/onnx/detectionoutput_ext.py extensions/front/onnx/dropout_ext.py +extensions/front/onnx/einsum_ext.py extensions/front/onnx/elementwise_ext.py extensions/front/onnx/expand_ext.py extensions/front/onnx/faster_rcnn.json @@ -404,6 +407,7 @@ extensions/front/tf/deconv_ext.py extensions/front/tf/depth_to_space.py extensions/front/tf/efficient_det_support_api_v2.0.json extensions/front/tf/efficient_det_support_api_v2.4.json +extensions/front/tf/einsum_ext.py extensions/front/tf/elementwise_ext.py extensions/front/tf/embedding_segments_sum.py extensions/front/tf/expand_dims_ext.py @@ -678,6 +682,7 @@ extensions/ops/dequantize_linear.py extensions/ops/DetectionOutput.py extensions/ops/detectionoutput_onnx.py extensions/ops/dft.py +extensions/ops/einsum.py extensions/ops/elementwise.py extensions/ops/embedding_bag.py extensions/ops/Enter.py @@ -1028,6 +1033,7 @@ mo/utils/ir_reader/extenders/convert_extender.py mo/utils/ir_reader/extenders/ctc_greedy_decoder_seq_len_extender.py mo/utils/ir_reader/extenders/deconvolution_extender.py mo/utils/ir_reader/extenders/deformable_convolution_extender.py +mo/utils/ir_reader/extenders/einsum_extender.py mo/utils/ir_reader/extenders/experimental_extender.py mo/utils/ir_reader/extenders/ExtractImagePatches_extender.py mo/utils/ir_reader/extenders/fakequantize_extender.py diff --git a/model-optimizer/extensions/back/LayoutChangeForEinsum.py b/model-optimizer/extensions/back/LayoutChangeForEinsum.py new file mode 100644 index 00000000000..f45bff54b93 --- /dev/null +++ b/model-optimizer/extensions/back/LayoutChangeForEinsum.py @@ -0,0 +1,57 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from extensions.ops.einsum import Einsum +from mo.back.replacement import BackReplacementPattern +from mo.graph.graph import Graph + + +class LayoutChangeForEinsum(BackReplacementPattern): + """ + The transformation adjusts Einsum equation to NCHW layout. + Subscripts for tensor of rank greater than three must be adjusted + to NCHW layout, meaning a label for the last dimension is moved + to the second position in the subscript. + There is an exception when the last label in the subscript is ellipsis + and covers multiple dimensions. In this case subscript is not changed and + Transpose to get original NHWC layout back is inserted. + The transformation is only applicable to TensorFlow case. + """ + enabled = True + force_shape_inference = True + graph_condition = [lambda graph: graph.graph['fw'] == 'tf'] + + def find_and_replace_pattern(self, graph: Graph): + import extensions.middle.InsertLayoutPropagationTransposes as InsertTransposes + for einsum in graph.get_op_nodes(type='Einsum'): + einsum_name = einsum.soft_get('name', einsum.id) + assert einsum.has_valid('equation'), "Equation attribute is mandatory" \ + " for Einsum node {}".format(einsum_name) + equation = einsum.equation + connected_in_ports = [port for port in einsum.in_ports().values() if not port.disconnected()] + num_inputs = len(connected_in_ports) + + # compute a mask of inputs of rank greater than 3 that are required original layout (NCHW) + # due to presence of ellipsis covering multiple tail dimensions in the corresponding input subscript + input_ranks = [len(einsum.in_port(port_idx).data.get_shape()) for port_idx in range(num_inputs)] + output_rank = len(einsum.out_port(0).data.get_shape()) + permuted_equation, is_inputs_permuted, is_output_permuted = Einsum.adjust_equation_with_NCHW_layout( + einsum_name, + equation, + input_ranks, + output_rank) + assert len(is_inputs_permuted) == num_inputs + + # setup adjusted equation + einsum.equation = permuted_equation + + # insert Transpose node to get NHWC layout back (for inputs) that is required due to specifics of equation + for input_ind in range(num_inputs): + if not is_inputs_permuted[input_ind]: + # that means Einsum can only accept input in NHWC layout + # so the inserted transpose before the Einsum will convert the layout to NHWC + InsertTransposes.insert_transpose(graph, einsum.in_port(input_ind), before_input=True) + if not is_output_permuted: + # that means Einsum can only generate output in NHWC layout + # so the inserted transpose followed after the output will convert the layout back into NCHW layout + InsertTransposes.insert_transpose(graph, einsum.out_port(0), before_input=False) diff --git a/model-optimizer/extensions/front/mxnet/einsum_ext.py b/model-optimizer/extensions/front/mxnet/einsum_ext.py new file mode 100644 index 00000000000..445cc38f242 --- /dev/null +++ b/model-optimizer/extensions/front/mxnet/einsum_ext.py @@ -0,0 +1,20 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from extensions.ops.einsum import Einsum +from mo.front.extractor import FrontExtractorOp +from mo.front.mxnet.extractors.utils import get_mxnet_layer_attrs + + +class EinsumExtractor(FrontExtractorOp): + op = '_npi_einsum' + enabled = True + + @classmethod + def extract(cls, einsum_node): + einsum_name = einsum_node.soft_get('name', einsum_node.id) + attrs = get_mxnet_layer_attrs(einsum_node.symbol_dict) + equation = attrs.str('subscripts') + normalized_equation = Einsum.normalize_equation(einsum_name, equation) + Einsum.update_node_stat(einsum_node, {'equation': normalized_equation}) + return cls.enabled diff --git a/model-optimizer/extensions/front/onnx/einsum_ext.py b/model-optimizer/extensions/front/onnx/einsum_ext.py new file mode 100644 index 00000000000..f2a0336ab65 --- /dev/null +++ b/model-optimizer/extensions/front/onnx/einsum_ext.py @@ -0,0 +1,19 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from extensions.ops.einsum import Einsum +from mo.front.extractor import FrontExtractorOp +from mo.front.onnx.extractors.utils import onnx_attr + + +class EinsumExtractor(FrontExtractorOp): + op = 'Einsum' + enabled = True + + @classmethod + def extract(cls, einsum_node): + einsum_name = einsum_node.soft_get('name', einsum_node.id) + equation = onnx_attr(einsum_node, 'equation', 's').decode(encoding="utf-8") + normalized_equation = Einsum.normalize_equation(einsum_name, equation) + Einsum.update_node_stat(einsum_node, {'equation': normalized_equation}) + return cls.enabled diff --git a/model-optimizer/extensions/front/tf/einsum_ext.py b/model-optimizer/extensions/front/tf/einsum_ext.py new file mode 100644 index 00000000000..290fa948183 --- /dev/null +++ b/model-optimizer/extensions/front/tf/einsum_ext.py @@ -0,0 +1,18 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from extensions.ops.einsum import Einsum +from mo.front.extractor import FrontExtractorOp + + +class EinsumExtractor(FrontExtractorOp): + op = 'Einsum' + enabled = True + + @classmethod + def extract(cls, einsum_node): + einsum_name = einsum_node.soft_get('name', einsum_node.id) + equation = einsum_node.pb.attr['equation'].s.decode('utf-8') + normalized_equation = Einsum.normalize_equation(einsum_name, equation) + Einsum.update_node_stat(einsum_node, {'equation': normalized_equation}) + return cls.enabled diff --git a/model-optimizer/extensions/ops/einsum.py b/model-optimizer/extensions/ops/einsum.py new file mode 100644 index 00000000000..907989216ac --- /dev/null +++ b/model-optimizer/extensions/ops/einsum.py @@ -0,0 +1,232 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import re + +import numpy as np + +from mo.front.common.partial_infer.utils import int64_array +from mo.graph.graph import Node, Graph +from mo.ops.op import Op +from mo.utils.broadcasting import bi_directional_shape_broadcasting + + +class Einsum(Op): + op = 'Einsum' + enabled = False + + def __init__(self, graph: Graph, attrs: dict): + mandatory_props = { + 'type': self.op, + 'op': self.op, + 'version': 'opset7', + 'infer': self.infer, + 'out_ports_count': 1, + } + super().__init__(graph, mandatory_props, attrs) + + def backend_attrs(self): + return ['equation'] + + @staticmethod + def parse_equation(node_name: str, equation: str) -> (list, str): + """ + Parse Einsum equation and check that its format is correct to make sure that + all input subscripts consists of only alphabetic letters or alphabetic letters with one ellipsis. + In case of implicit mode the method recovers the right-hand part. + + :param node_name: Einsum node name for which to parse an equation + :param equation: Equation to be parsed and checked + :return: A tuple of a list of input subscripts and output subscript + """ + # normalize equation by removing white-spaces + equation = equation.strip() + + # split equation into the left and right hands + splitted_equation = equation.split('->') + assert len(splitted_equation) <= 2, "Einsum node {} has `equation` of incorrect format".format(node_name) + + # split left-hand side of the equation and check a format of input subscripts + input_subscripts = splitted_equation[0] + input_subscripts_list = input_subscripts.split(',') + + # prepare pattern to check a format of subscripts + subscript_pattern = re.compile("^[a-zA-Z]*(\\.\\.\\.){0,1}[a-zA-Z]*$") + ellipsis_pattern = re.compile("\\.\\.\\.") + + is_ellipsis_met = False + for input_subscript in input_subscripts_list: + assert re.match(subscript_pattern, input_subscript) is not None, \ + "Einsum node {} has `equation` with incorrect input subscript: {}".format(node_name, input_subscript) + is_ellipsis_met = is_ellipsis_met or re.search(ellipsis_pattern, input_subscript) + + if len(splitted_equation) == 2: + output_subscript = splitted_equation[1] + assert re.match(subscript_pattern, output_subscript), \ + "Einsum node {} has `equation` with incorrect output subscript: {}".format(node_name, output_subscript) + # if ellipsis is met, the output subscript must contain it as well + if is_ellipsis_met: + assert re.search(ellipsis_pattern, output_subscript), \ + "The output subscript of Einsum node {} must contain ellipsis".format(node_name) + elif len(splitted_equation) == 1: + # recover output subscript in case implicit mode + output_subscript = ''.join(input_subscripts_list) + output_subscript = ''.join(sorted(list(set(output_subscript) - {'.'}))) + if is_ellipsis_met: + output_subscript = "..." + output_subscript + else: + assert False, "Einsum node {} equation has incorrect format. " \ + "It must be in either explicit or implicit mode.".format(node_name) + + return input_subscripts_list, output_subscript + + @staticmethod + def normalize_equation(node_name: str, equation: str) -> str: + """ + Recover explicit mode of equation. + + :param node_name: Einsum node name for which to recover explicit mode + :param equation: Einsum equation to recover explicit mode + :return: Recovered equation in explicit mode + """ + input_subscripts_list, output_subscript = Einsum.parse_equation(node_name, equation) + return ','.join(input_subscripts_list) + "->" + output_subscript + + @staticmethod + def extract_subscript_labels(node_name: str, subscript: str) -> list: + """ + Extract labels for given subscript. Each label can be either alphabetic letter or ellipsis + + :param node_name: Einsum node name + :param subscript: Given subscript + :return: A list of labels + """ + labels = [] + len_subscript = len(subscript) + label_ind = 0 + while label_ind < len_subscript: + if subscript[label_ind].isalpha(): + labels.append(subscript[label_ind]) + label_ind += 1 + elif len_subscript - label_ind > 2 and subscript[label_ind:label_ind + 3] == "...": + labels.append("...") + label_ind += 3 + else: + assert False, "Einsum node {} has `equation` with incorrect subscript: {}".format(node_name, subscript) + return labels + + @staticmethod + def adjust_equation_with_NCHW_layout(node_name: str, equation: str, input_ranks: list, output_rank: int) -> ( + str, list, bool): + """ + In order to satisfy NCHW layout, subscripts for tensors with rank greater than three must be adjusted by moving labels + of the last dimension to the second position in the subscript. There is an exception for such tensors when + the label is ellipsis and it covers multiple tail dimensions. The method returns equation with adjusted subscripts + to NCHW layout along with a boolean mask to indicate which subscripts are adjusted. + + :param node_name: Einsum node name for which equation is adjusted + :param equation: Equation to be adjusted + :param input_ranks: a list of input ranks + :param output_rank: output rank + :return: adjusted equation, boolean mask for inputs, and boolean flag if output subscript is adjusted + """ + is_inputs_permuted = [] + input_subscripts, output_subscript = Einsum.parse_equation(node_name, equation) + num_inputs = len(input_ranks) + assert len(input_subscripts) == num_inputs, "The number of inputs must match a number " \ + "of input subscripts" + + # permute labels in input subscripts and mark inputs for which inference in NCHW layout is acceptable + # in case ellipsis covering multiple dimensions in the end, the permutation is impossible + # so the corresponding input must be in the original format (NHWC) + permuted_input_subscripts = [] + for input_ind in range(num_inputs): + input_subscript = input_subscripts[input_ind] + input_rank = input_ranks[input_ind] + labels = Einsum.extract_subscript_labels(node_name, input_subscript) + num_broadcasted_dims = input_rank - len(labels) + 1 + if input_rank > 3 and (labels[-1] != "..." or labels[-1] == "..." and num_broadcasted_dims == 1): + is_inputs_permuted.append(True) + labels.insert(1, labels[-1]) + del labels[-1] + else: + is_inputs_permuted.append(False) + permuted_input_subscript = ''.join(labels) + permuted_input_subscripts.append(permuted_input_subscript) + + # perform the same procedure for the output subscript as for the inputs subscripts + labels = Einsum.extract_subscript_labels(node_name, output_subscript) + num_broadcasted_dims = output_rank - len(labels) + 1 + if output_rank > 3 and (labels[-1] != "..." or labels[-1] == "..." and num_broadcasted_dims == 1): + is_output_permuted = True + labels.insert(1, labels[-1]) + del labels[-1] + else: + is_output_permuted = False + permuted_output_subscript = ''.join(labels) + + # concatenate the left and right hands of the resulted equation + left_hand = ','.join(permuted_input_subscripts) + right_hand = permuted_output_subscript + permuted_equation = left_hand + "->" + right_hand + return permuted_equation, is_inputs_permuted, is_output_permuted + + @staticmethod + def infer(node: Node): + node_name = node.soft_get('name', node.id) + connected_in_ports = [port for port in node.in_ports().values() if not port.disconnected()] + num_inputs = len(connected_in_ports) + assert node.has_valid('equation'), "Einsum node {} must contain `equation` attribute".format(node_name) + equation = node.equation + + # parse the equation and extract input and output subscripts + input_subscripts, output_subscript = Einsum.parse_equation(node_name, equation) + + # check that each operand has the corresponding input subscript + assert len(input_subscripts) == num_inputs, "The number of input operands of Einsum node {} " \ + "must match the number of input subscripts " \ + "in `equation`".format(node_name) + + # check compatibility of dimension sizes with the same label and generate a dictionary of shapes for labels + label_to_shape = {} + for input_ind in range(num_inputs): + input_shape = node.in_port(input_ind).data.get_shape() + input_subscript = input_subscripts[input_ind] + labels = Einsum.extract_subscript_labels(node_name, input_subscript) + num_dims = len(input_shape) + num_labels = len(labels) + num_broadcasted_dims = num_dims - num_labels + 1 + dim_ind = 0 + label_ind = 0 + while label_ind < num_labels and dim_ind < num_dims: + label = labels[label_ind] + if label == "...": + sub_shape = input_shape[dim_ind:dim_ind + num_broadcasted_dims] + if label in label_to_shape.keys(): + common_shape = bi_directional_shape_broadcasting(sub_shape, label_to_shape[label]) + assert common_shape is not None, "The dimensions labeled of ellipsis must be broadcastable " \ + "for Einsum node {}".format(node_name) + label_to_shape[label] = common_shape + else: + label_to_shape[label] = sub_shape + dim_ind += num_broadcasted_dims + else: + dim_size = input_shape[dim_ind] + sub_shape = int64_array([dim_size]) + assert label not in label_to_shape.keys() or np.array_equal(label_to_shape[label], sub_shape), \ + "Sizes of dimensions with the same label of Einsum node {} " \ + "must be compatible".format(node_name) + label_to_shape[label] = sub_shape + dim_ind += 1 + label_ind += 1 + + # generate output shape based on the output subscript + output_shape = int64_array([]) + labels = Einsum.extract_subscript_labels(node_name, output_subscript) + for label in labels: + assert label in label_to_shape.keys(), "The label in the output subscript must appear" \ + " in input subscripts in equation {} " \ + "of Einsum node {}".format(equation, node_name) + output_shape = np.concatenate((output_shape, label_to_shape[label])) + + node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/mo/utils/ir_reader/extenders/einsum_extender.py b/model-optimizer/mo/utils/ir_reader/extenders/einsum_extender.py new file mode 100644 index 00000000000..1cb3e35bc52 --- /dev/null +++ b/model-optimizer/mo/utils/ir_reader/extenders/einsum_extender.py @@ -0,0 +1,17 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from mo.utils.graph import Node +from mo.utils.ir_reader.extender import Extender + + +class Einsum_extender(Extender): + op = 'Einsum' + + @staticmethod + def extend(op: Node): + einsum_name = op.soft_get('name', op.id) + if isinstance(op['equation'], list): + op['equation'] = ','.join(op['equation']) + elif not isinstance(op['equation'], str): + assert False, "Equation of Einsum node {} has incorrect format.".format(einsum_name) diff --git a/model-optimizer/unit_tests/extensions/back/LayoutChangeForEinsum_test.py b/model-optimizer/unit_tests/extensions/back/LayoutChangeForEinsum_test.py new file mode 100644 index 00000000000..45e0f2badab --- /dev/null +++ b/model-optimizer/unit_tests/extensions/back/LayoutChangeForEinsum_test.py @@ -0,0 +1,82 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +import numpy as np + +from extensions.back.LayoutChangeForEinsum import LayoutChangeForEinsum +from mo.front.common.partial_infer.utils import int64_array +from mo.utils.ir_engine.compare_graphs import compare_graphs +from unit_tests.utils.graph import build_graph, result, regular_op_with_shaped_data, valued_const_with_data, connect + +nodes_attributes = { + # Parameter layers + **regular_op_with_shaped_data('placeholder_1', None, {'type': 'Parameter', 'op': 'Parameter'}), + **regular_op_with_shaped_data('placeholder_2', None, {'type': 'Parameter', 'op': 'Parameter'}), + **regular_op_with_shaped_data('placeholder_3', None, {'type': 'Parameter', 'op': 'Parameter'}), + + # Einsum layer + **regular_op_with_shaped_data('einsum', None, {'type': 'Einsum', 'op': 'Einsum'}), + + # Result layer + **result(), + + # Transpose layers + **regular_op_with_shaped_data('transpose_1', None, + {'type': 'Transpose', 'op': 'Transpose', 'need_shape_inference': True}), + **regular_op_with_shaped_data('transpose_3', None, + {'type': 'Transpose', 'op': 'Transpose', 'need_shape_inference': True}), + + # Const layers + **valued_const_with_data('axis_1_const', int64_array([0, 2, 3, 1])), + **valued_const_with_data('axis_3_const', int64_array([0, 4, 1, 2, 3])), +} + + +class LayoutChangeForEinsumTests(unittest.TestCase): + def test_layout_change_einsum(self): + graph = build_graph(nodes_attributes, + [*connect('placeholder_1', '0:einsum'), + *connect('placeholder_2', '1:einsum'), + *connect('placeholder_3', '2:einsum'), + *connect('einsum', 'output')], + { # this input stays as is since it is of a rank equal to 3 + 'placeholder_1_d': {'shape': np.array([2, 3, 5])}, + # [3, 5, 7, 8] - NHWC, [3, 8, 5, 7] - NCHW + # this input does not require additional transpose + # since the corresponding subscript can be adjusted + 'placeholder_2_d': {'shape': np.array([3, 8, 5, 7])}, + # [3, 5, 10, 12] - NHWC, [3, 12, 5, 10] - NCHW + # the third input must be transposed to NHWC layout + # since ellipsis covers multiple dimensions in the end + # the corresponding subscript is not changed + 'placeholder_3_d': {'shape': np.array([3, 12, 8, 10])}, + # equation is still for NHWC layout + 'einsum': {'equation': "abc,bcde,bc...->ade..."}, + # [2, 7, 8, 10, 12] - NHWC, [2, 12, 7, 8, 10] - NCHW + # the output is in NCHW layout but its shape will be re-inferred since + # the output stays in NHWC layout due to ellipsis in the end + # and additional transpose to NCHW will be inserted + 'einsum_d': {'shape': np.array([2, 12, 7, 8, 10])}, + }, nodes_with_edges_only=True) + graph.graph['fw'] = 'tf' + + graph_ref = build_graph(nodes_attributes, + [*connect('placeholder_3', '0:transpose_1'), + *connect('axis_1_const', '1:transpose_1'), + *connect('placeholder_1', '0:einsum'), + *connect('placeholder_2', '1:einsum'), + *connect('transpose_1', '2:einsum'), + *connect('einsum', '0:transpose_3'), + *connect('axis_3_const', '1:transpose_3'), + *connect('transpose_3', 'output')], + {'placeholder_1_d': {'shape': np.array([2, 3, 5])}, + 'placeholder_2_d': {'shape': np.array([3, 8, 5, 7])}, + 'einsum': {'equation': "abc,becd,bc...->ade..."}, + 'einsum_d': {'shape': np.array([2, 12, 7, 8, 10])} + }) + + LayoutChangeForEinsum().find_and_replace_pattern(graph) + (flag, resp) = compare_graphs(graph, graph_ref, 'output', check_op_attrs=True) + self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/ops/einsum_test.py b/model-optimizer/unit_tests/extensions/ops/einsum_test.py new file mode 100644 index 00000000000..9407fe63d5f --- /dev/null +++ b/model-optimizer/unit_tests/extensions/ops/einsum_test.py @@ -0,0 +1,90 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +import numpy as np +from generator import generator, generate + +from extensions.ops.einsum import Einsum +from mo.front.common.partial_infer.utils import int64_array +from mo.graph.graph import Graph +from mo.graph.graph import Node +from unit_tests.utils.graph import build_graph, regular_op_with_shaped_data, result, connect + + +def create_einsum_graph(input_shapes: list, equation: str) -> Graph: + num_inputs = len(input_shapes) + assert num_inputs > 0, "Einsum node must have at least one input" + nodes = {} + edges = [] + for input_ind in range(num_inputs): + input_name = 'input' + str(input_ind) + parameter_op = regular_op_with_shaped_data(input_name, input_shapes[input_ind], + {'op': 'Parameter', 'type': 'Parameter'}) + nodes.update(parameter_op) + edges += connect(input_name, str(input_ind) + ":einsum_node") + einsum_op = regular_op_with_shaped_data('einsum_node', None, + {'op': 'Einsum', 'type': 'Einsum', 'equation': equation}) + nodes.update(einsum_op) + result_op = result('output') + nodes.update(result_op) + edges += connect('einsum_node', 'output') + + graph = build_graph(nodes, edges, nodes_with_edges_only=True) + return graph + + +@generator +class TestEinsum(unittest.TestCase): + @generate(*[ + # dot product + ([int64_array([10]), int64_array([10])], "i,i->", int64_array([])), + # matrix multiplication + ([int64_array([2, 3]), int64_array([3, 4])], "ab,bc->ac", int64_array([2, 4])), + # trace per batch + ([int64_array([2, 3, 3])], "kii->k", int64_array([2])), + # diagonal extraction + ([int64_array([6, 5, 5])], "kii->ki", int64_array([6, 5])), + # transpose + ([int64_array([1, 2, 3])], "ijk->kij", int64_array([3, 1, 2])), + # multiple matrix multiplication + ([int64_array([2, 5]), int64_array([5, 3, 6]), int64_array([5, 3])], "ab,bcd,bc->ca", int64_array([3, 2])), + # ellipsis for one operand + ([int64_array([5, 3, 4])], "a...->...", int64_array([3, 4])), + # ellipsis for multiple operands + ([int64_array([3, 5]), int64_array([1])], "a...,...->a...", int64_array([3, 5])), + # ellipsis with broadcasting + ([int64_array([9, 1, 4, 3]), int64_array([3, 11, 7, 1])], "a...b,b...->a...", int64_array([9, 11, 7, 4])), + # mixed case letters in equation + ([int64_array([1, 3, 5])], "AbC", int64_array([1, 5, 3])), + # mixed case letters and equation in implicit mode + ([int64_array([3, 11, 1, 5]), int64_array([1, 3, 1, 7])], "a...b,B...", int64_array([3, 11, 7, 1, 3, 5])), + ]) + def test_einsum(self, input_shapes, equation, ref_output_shape): + graph = create_einsum_graph(input_shapes, equation) + einsum_node = Node(graph, 'einsum_node') + Einsum.infer(einsum_node) + + # get the result + res_output_shape = graph.node['einsum_node_d']['shape'] + + self.assertTrue(np.array_equal(ref_output_shape, res_output_shape), + 'shape does not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + + @generate(*[ + # incorrect subscript numbers or inputs + ([int64_array([3, 11]), int64_array([11, 4])], "ab,bc,cd->ac", None), + # invalid labels + ([int64_array([3, 11]), int64_array([11, 4])], "a$,Bc->ac", None), + # incompatible shapes + ([int64_array([3, 11]), int64_array([12, 4])], "ab,bc->ac", None), + # not broadcastable shapes + ([int64_array([11, 1, 4, 3]), int64_array([3, 11, 7, 5])], "a...b,b...->a...", None), + # missed ellipsis + ([int64_array([11, 1, 4, 3]), int64_array([3, 11, 7, 4])], "a...b,b...->a", None), + ]) + def test_invalid_cases(self, input_shapes, equation, ref_output_shape): + graph = create_einsum_graph(input_shapes, equation) + einsum_node = Node(graph, 'einsum_node') + self.assertRaises(AssertionError, Einsum.infer, einsum_node) diff --git a/model-optimizer/unit_tests/extensions/ops/gathernd_test.py b/model-optimizer/unit_tests/extensions/ops/gathernd_test.py index 74217e26e53..2482a5b022b 100644 --- a/model-optimizer/unit_tests/extensions/ops/gathernd_test.py +++ b/model-optimizer/unit_tests/extensions/ops/gathernd_test.py @@ -14,7 +14,7 @@ nodes_attributes = {'data': {'kind': 'op'}, 'data_data': {'shape': None, 'value': None, 'kind': 'data'}, 'indices': {'kind': 'op'}, 'indices_data': {'shape': None, 'value': None, 'kind': 'data'}, - 'gathernd_node': {'op': 'ScatterNDUpdate', 'kind': 'op', 'batch_dims': 0}, + 'gathernd_node': {'op': 'GatherNDUpdate', 'kind': 'op', 'batch_dims': 0}, 'output': {'shape': None, 'value': None, 'kind': 'data'}} # graph 1 @@ -118,7 +118,7 @@ inputs_inv2 = {'data_data': {'shape': int64_array([10, 40, 20]), 'value': None}, inputs_inv3 = {'data_data': {'shape': int64_array([10, 40, 20, 10, 2]), 'value': None}, 'indices_data': {'shape': int64_array([10, 40, 4]), 'value': None}} -class TestScatterNDUpdate(unittest.TestCase): +class TestGatherNDUpdate(unittest.TestCase): def setUp(self): nodes_attributes['gathernd_node']['batch_dims'] = 0 From 0b22d6c51c1be370576032f9480bf7b44bb5165d Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Tue, 11 May 2021 22:29:59 +0300 Subject: [PATCH 14/99] Add Gather-7 to MO (#5264) * initial solution * added unit-tests + some corrections * axis getting improvements * fixed MO IR reader for old IR's * a couple of corrections * applied review comments * corrected negative batch_dims normalization for shape calculation, for IR original negative values are kept * added additional checks and negative tests --- .../extensions/front/tf/gather_ext.py | 2 +- model-optimizer/extensions/ops/gather.py | 61 +++-- .../unit_tests/extensions/ops/gather_test.py | 225 ++++++++++++++---- model-optimizer/unit_tests/utils/graph.py | 5 + 4 files changed, 236 insertions(+), 57 deletions(-) diff --git a/model-optimizer/extensions/front/tf/gather_ext.py b/model-optimizer/extensions/front/tf/gather_ext.py index 8af73b15502..faad2f22388 100644 --- a/model-optimizer/extensions/front/tf/gather_ext.py +++ b/model-optimizer/extensions/front/tf/gather_ext.py @@ -31,5 +31,5 @@ class GatherV2FrontExtractor(FrontExtractorOp): @classmethod def extract(cls, node): - Gather.update_node_stat(node, {}) + Gather.update_node_stat(node, {'batch_dims': node.pb.attr['batch_dims'].i}) return cls.enabled diff --git a/model-optimizer/extensions/ops/gather.py b/model-optimizer/extensions/ops/gather.py index 3396a639e7e..e5ca196fca7 100644 --- a/model-optimizer/extensions/ops/gather.py +++ b/model-optimizer/extensions/ops/gather.py @@ -7,6 +7,7 @@ from mo.front.caffe.extractors.utils import get_canonical_axis_index from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node, Graph from mo.ops.op import Op, PermuteAttrs +from mo.utils.error import Error class Gather(Op): @@ -17,12 +18,10 @@ class Gather(Op): super().__init__(graph, { 'op': self.op, 'type': self.op, - 'version': 'opset1', - + 'version': 'opset7', + 'batch_dims': 0, 'infer': self.infer, - 'force_precision_in_ports': {1: 'int32', 2: 'int64'}, - 'in_ports_count': 3, 'out_ports_count': 1, }, attrs) @@ -30,6 +29,15 @@ class Gather(Op): assert 'axis' not in self.attrs, \ 'Use AttributedGather operation instead of Gather to create it with `axis` as a parameter' + def backend_attrs(self): + version = self.get_opset() + if version == 'opset7': + return ['batch_dims'] + elif version == 'opset1': + return [] + else: + raise Error('Unsupported operation opset version "{}"'.format(version)) + @staticmethod def infer(node: Node): name = node.soft_get('name', node.id) @@ -44,25 +52,46 @@ class Gather(Op): indices_shape = node.in_port(1).data.get_shape() assert indices_shape is not None axis = node.in_port(2).data.get_value() - assert axis is not None - axis = get_canonical_axis_index(data_shape, axis) + assert axis is not None, 'axis input is undefined' + + assert -len(data_shape) <= axis < len(data_shape), \ + 'axis must be within interval [-data_rank, data_rank). Instead got axis = {}, data_rank = {} '.\ + format(axis, len(data_shape)) + + batch_dims = node.batch_dims + assert -len(indices_shape) <= batch_dims <= len(indices_shape), \ + 'batch_dims must be within interval [-indices_rank, indices_rank]. Instead got batch_dims = {}, ' \ + 'indices_rank = {} '.format(batch_dims, len(indices_shape)) + + # normalize to positive values + axis = axis + len(data_shape) if axis < 0 else axis + batch_dims = batch_dims + len(indices_shape) if batch_dims < 0 else batch_dims + + assert np.array_equal(data_shape[:batch_dims], indices_shape[:batch_dims]), \ + 'data and indices inputs must have equal first dimensions until batch_dims' + + assert batch_dims <= axis, \ + 'normalized batch_dims must be <= axis. Instead got batch_dims = {}, axis = {}'.format(axis, batch_dims) # we import PermuteInputs locally because it uses Gather inside and we have recursive imports from mo.graph.perm_inputs import PermuteInputs PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:0', 'axis') + batch_dims_range = indices_shape[:batch_dims] + out_shape = np.concatenate((data_shape[:axis], indices_shape[batch_dims:], data_shape[axis + 1:])) + data_value = node.in_port(0).data.get_value() indices_value = node.in_port(1).data.get_value() if data_value is not None and indices_value is not None: - node.out_port(0).data.set_value(np.array(np.take(data_value, int64_array(indices_value), axis), - dtype=data_value.dtype)) - return - - shape = np.concatenate((data_shape[:axis], indices_shape)) - if axis < len(data_shape) - 1: - shape = np.concatenate((shape, data_shape[axis + 1:])) - - node.out_port(0).data.set_shape(int64_array(shape)) + if batch_dims == 0: + node.out_port(0).data.set_value(np.take(data_value, indices_value, axis)) + else: + out_value = np.empty(out_shape) + for batch_idx in np.ndindex(tuple(batch_dims_range)): + out_value[batch_idx] = np.take(data_value[batch_idx], indices_value[batch_idx], axis - batch_dims) + node.out_port(0).data.set_value(out_value) + else: + node.out_port(0).data.set_shape(int64_array(out_shape)) class AttributedGather(Op): @@ -80,7 +109,7 @@ class AttributedGather(Op): 'force_precision_in_ports': {1: 'int32'}, - 'in_ports_count': 3, + 'in_ports_count': 2, 'out_ports_count': 1, }, attrs) diff --git a/model-optimizer/unit_tests/extensions/ops/gather_test.py b/model-optimizer/unit_tests/extensions/ops/gather_test.py index d71445936b0..4891e4d8b92 100644 --- a/model-optimizer/unit_tests/extensions/ops/gather_test.py +++ b/model-optimizer/unit_tests/extensions/ops/gather_test.py @@ -3,59 +3,204 @@ import unittest -import numpy as np +import numpy.testing as npt from extensions.ops.gather import Gather from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node -from unit_tests.utils.graph import build_graph +from mo.middle.passes.infer import partial_infer +from mo.utils.error import Error +from unit_tests.utils.graph import valued_const_with_data, result, regular_op_with_empty_data, connect, \ + shaped_parameter, build_graph class TestGatherPartialInfer(unittest.TestCase): + @staticmethod - def _create_graph(): - nodes_attributes = { - - 'gather_input': {'kind': 'op'}, - 'gather_input_data': {'shape': None, 'value': None, 'kind': 'data'}, - 'gather_input2': {'kind': 'op'}, - 'gather_input2_data': {'shape': None, 'value': None, 'kind': 'data'}, - 'gather_input3': {'kind': 'op'}, - 'gather_input3_data': {'shape': None, 'value': 0, 'kind': 'data'}, - - 'gather_node': {'op': 'Gather', 'kind': 'op'}, - 'gather_output': {'shape': None, 'value': None, 'kind': 'data'} - + def build_and_test_value_inference(data, indices, axis, batch_dims, ref_value, negative_test_string=None): + nodes = { + **valued_const_with_data('data', int64_array(data)), + **valued_const_with_data('indices', int64_array(indices)), + **valued_const_with_data('axis', int64_array(axis)), + **regular_op_with_empty_data('gather', {'op': 'Gather', 'batch_dims': batch_dims, 'infer': Gather.infer}), + **result('res'), } - return build_graph(nodes_attributes, - [ - ('gather_input', 'gather_input_data'), - ('gather_input2', 'gather_input2_data'), - ('gather_input3', 'gather_input3_data'), - ('gather_input_data', 'gather_node'), - ('gather_input2_data', 'gather_node'), - ('gather_input3_data', 'gather_node'), + edges = [ + *connect('data', '0:gather'), + *connect('indices', '1:gather'), + *connect('axis', '2:gather'), + *connect('gather', 'res') + ] - ('gather_node', 'gather_output'), - ], - { - 'gather_input_data': {'shape': int64_array([10, 15]), 'value': np.ones((3, 15))}, - 'gather_input2_data': {'shape': int64_array([2]), 'value': np.array([0, 2])}, - }) + graph = build_graph(nodes, edges) + graph.stage = 'middle' + partial_infer(graph) - def test_gather_infer(self): - graph = self._create_graph() + node = Node(graph, 'gather') + res = node.out_port(0).data.get_value() + npt.assert_array_equal(res, ref_value) - gather_node = Node(graph, 'gather_node') - Gather.infer(gather_node) + @staticmethod + def build_and_test_shape_inference(data_shape, indices_shape, axis, batch_dims, ref_shape): + nodes = { + **shaped_parameter('data', int64_array(data_shape)), + **shaped_parameter('indices', int64_array(indices_shape)), + **valued_const_with_data('axis', int64_array(axis)), + **regular_op_with_empty_data('gather', {'op': 'Gather', 'batch_dims': batch_dims, 'infer': Gather.infer}), + **result('res'), + } - exp_shape = int64_array([2, 15]) - res_shape = graph.node['gather_output']['shape'] - res_value = graph.node['gather_output']['value'] + edges = [ + *connect('data', '0:gather'), + *connect('indices', '1:gather'), + *connect('axis', '2:gather'), + *connect('gather', 'res') + ] - self.assertTrue(np.array_equal(exp_shape, res_shape), - 'shapes do not match expected: {} and given: {}'.format(exp_shape, res_shape)) + graph = build_graph(nodes, edges) + graph.stage = 'middle' + partial_infer(graph) - self.assertTrue(np.array_equal(res_value, np.ones(exp_shape)), - 'shapes do not match expected: {} and given: {}'.format(exp_shape, res_shape)) + node = Node(graph, 'gather') + res = node.out_port(0).data.get_shape() + npt.assert_array_equal(res, ref_shape) + + def test_shape_axis_1(self): + self.build_and_test_shape_inference(axis=1, batch_dims=0, + data_shape=[3, 3], + indices_shape=[1, 2], + ref_shape=[3, 1, 2]) + + def test_shape_axis_0(self): + self.build_and_test_shape_inference(axis=0, batch_dims=0, + data_shape=[3, 3], + indices_shape=[1, 2], + ref_shape=[1, 2, 3]) + + def test_shape_axis_minus_2(self): + self.build_and_test_shape_inference(axis=-2, batch_dims=0, + data_shape=[2, 3, 7], + indices_shape=[1, 4], + ref_shape=[2, 1, 4, 7]) + + def test_shape_axis_1_batch_dims_1(self): + self.build_and_test_shape_inference(axis=1, batch_dims=1, + data_shape=[3, 4], + indices_shape=[3, 1, 2], + ref_shape=[3, 1, 2]) + + def test_shape_axis_2_batch_dims_1(self): + self.build_and_test_shape_inference(axis=2, batch_dims=1, + data_shape=[3, 4, 7], + indices_shape=[3, 1, 2], + ref_shape=[3, 4, 1, 2]) + + def test_shape_axis_2_batch_dims_minus_1(self): + self.build_and_test_shape_inference(axis=2, batch_dims=-1, + data_shape=[3, 1, 7], + indices_shape=[3, 1, 2], + ref_shape=[3, 1, 2]) + + def test_shape_axis_2_batch_dims_minus_2(self): + self.build_and_test_shape_inference(axis=2, batch_dims=-2, + data_shape=[3, 4, 7], + indices_shape=[3, 1, 2], + ref_shape=[3, 4, 1, 2]) + + def test_axis_0_batch_dims_0(self): + self.build_and_test_value_inference(axis=0, batch_dims=0, + data=[1, 2, 3, 4, 5], + indices=[0, 0, 4], + ref_value=[1, 1, 5]) + + def test_axis_1_batch_dims_1(self): + self.build_and_test_value_inference(axis=1, batch_dims=1, + data=[[1, 2, 3, 4, 5], + [6, 7, 8, 9, 10]], + indices=[[0, 0, 4], + [4, 0, 0]], + + ref_value=[[1, 1, 5], + [10, 6, 6]]) + + def test_axis_minus_1_batch_dims_1(self): + self.build_and_test_value_inference(axis=-1, batch_dims=1, + data=[[1, 2, 3, 4, 5], + [6, 7, 8, 9, 10]], + indices=[[0, 0, 4], + [4, 0, 0]], + + ref_value=[[1, 1, 5], + [10, 6, 6]]) + + def test_axis_2_batch_dims_1(self): + self.build_and_test_value_inference(axis=2, batch_dims=1, + data=[[[[ 1, 2, 3, 4], # <-- first batch + [ 5, 6, 7, 8], + [ 9, 10, 11, 12], + [13, 14, 15, 16], + [17, 18, 19, 20]]], + [[[21, 22, 23, 24], # < -- second batch + [25, 26, 27, 28], + [29, 30, 31, 32], + [33, 34, 35, 36], + [37, 38, 39, 40]]]], # data_shape = (2, 1, 5, 4) + indices=[[1, 2, 4], + [4, 3, 2]], + ref_value=[[[[ 5, 6, 7, 8], + [ 9, 10, 11, 12], + [17, 18, 19, 20]]], + [[[37, 38, 39, 40], + [33, 34, 35, 36], + [29, 30, 31, 32]]]]) + + def test_axis_2_batch_dims_mimus_1(self): + self.build_and_test_value_inference(axis=2, batch_dims=-1, + data=[[[[ 1, 2, 3, 4], # <-- first batch + [ 5, 6, 7, 8], + [ 9, 10, 11, 12], + [13, 14, 15, 16], + [17, 18, 19, 20]]], + [[[21, 22, 23, 24], # < -- second batch + [25, 26, 27, 28], + [29, 30, 31, 32], + [33, 34, 35, 36], + [37, 38, 39, 40]]]], # data_shape = (2, 1, 5, 4) + indices=[[1, 2, 4], + [4, 3, 2]], + ref_value=[[[[ 5, 6, 7, 8], + [ 9, 10, 11, 12], + [17, 18, 19, 20]]], + [[[37, 38, 39, 40], + [33, 34, 35, 36], + [29, 30, 31, 32]]]]) + + # negative tests + def test_shape_indices_data_shape_inconsistency(self): + self.assertRaises(Error, self.build_and_test_shape_inference, + axis=2, batch_dims=2, + data_shape=[3, 4, 7], + indices_shape=[3, 1, 2], + ref_shape=[3, 4, 2]) + + def test_shape_batch_dims_greater_than_axis(self): + self.assertRaises(Error, self.build_and_test_shape_inference, + axis=2, batch_dims=3, + data_shape=[3, 4, 7], + indices_shape=[3, 4, 2], + ref_shape=[3, 4, 2]) + + def test_shape_batch_dims_out_of_bound(self): + self.assertRaises(Error, self.build_and_test_shape_inference, + axis=2, batch_dims=4, + data_shape=[3, 4, 7], + indices_shape=[3, 4, 2], + ref_shape=[3, 4, 2]) + + def test_shape_axis_out_of_bound(self): + self.assertRaises(Error, self.build_and_test_shape_inference, + axis=3, batch_dims=2, + data_shape=[3, 4, 7], + indices_shape=[3, 4, 2], + ref_shape=[3, 4, 2]) diff --git a/model-optimizer/unit_tests/utils/graph.py b/model-optimizer/unit_tests/utils/graph.py index c09abb0e208..1b349ed939a 100644 --- a/model-optimizer/unit_tests/utils/graph.py +++ b/model-optimizer/unit_tests/utils/graph.py @@ -6,6 +6,7 @@ from copy import deepcopy import networkx as nx +from extensions.ops.parameter import Parameter from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node, Graph from mo.middle.pattern_match import all_edges_in_nodes @@ -275,6 +276,10 @@ shaped_data = lambda name, shape: {name: {'kind': 'data', 'value': None, 'shape': int64_array(shape) if shape is not None else None}} empty_data = lambda name: valued_data(name, None) +shaped_parameter = lambda name, shape: {**regular_op(name, {'op': 'Parameter', 'shape': shape, + 'infer': Parameter.infer}), + **shaped_data(name + '_d', shape)} + result = lambda name=None: {name if name is not None else 'output': {'kind': 'op', 'type': 'Result', 'op': 'Result', 'infer': lambda x: 0}} From 5a0bcf50c331268f19bdc0ac59f9c4d341f05c09 Mon Sep 17 00:00:00 2001 From: Gabriele Galiero Casay Date: Wed, 12 May 2021 05:23:14 +0200 Subject: [PATCH 15/99] Add nGraph visitor tests for reduction operations (#5538) * Add ngraph visitor tests for reduction operations * Add check for number of expected attributes * Add ReduceL1 and ReduceL2 to visitor test typed case of reduce ops * Instantiate reduce operation type in separate file --- ngraph/test/CMakeLists.txt | 2 + ngraph/test/visitors/op/reduce_l1.cpp | 8 ++++ ngraph/test/visitors/op/reduce_l2.cpp | 8 ++++ .../test/visitors/op/reduce_logical_and.cpp | 33 ++----------- ngraph/test/visitors/op/reduce_logical_or.cpp | 33 ++----------- ngraph/test/visitors/op/reduce_max.cpp | 33 ++----------- ngraph/test/visitors/op/reduce_mean.cpp | 33 ++----------- ngraph/test/visitors/op/reduce_min.cpp | 33 ++----------- ngraph/test/visitors/op/reduce_ops.hpp | 48 +++++++++++++++++++ ngraph/test/visitors/op/reduce_prod.cpp | 33 ++----------- ngraph/test/visitors/op/reduce_sum.cpp | 33 ++----------- 11 files changed, 87 insertions(+), 210 deletions(-) create mode 100644 ngraph/test/visitors/op/reduce_l1.cpp create mode 100644 ngraph/test/visitors/op/reduce_l2.cpp create mode 100644 ngraph/test/visitors/op/reduce_ops.hpp diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 703d0ecbe8d..07d2632172e 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -237,6 +237,8 @@ set(SRC visitors/op/prior_box.cpp visitors/op/proposal.cpp visitors/op/psroi_pooling.cpp + visitors/op/reduce_l1.cpp + visitors/op/reduce_l2.cpp visitors/op/reduce_logical_and.cpp visitors/op/reduce_logical_or.cpp visitors/op/reduce_max.cpp diff --git a/ngraph/test/visitors/op/reduce_l1.cpp b/ngraph/test/visitors/op/reduce_l1.cpp new file mode 100644 index 00000000000..a9e9c631871 --- /dev/null +++ b/ngraph/test/visitors/op/reduce_l1.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "reduce_ops.hpp" + +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_l1, ReduceOpsAttrTest, Type); diff --git a/ngraph/test/visitors/op/reduce_l2.cpp b/ngraph/test/visitors/op/reduce_l2.cpp new file mode 100644 index 00000000000..0a592e65c9b --- /dev/null +++ b/ngraph/test/visitors/op/reduce_l2.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "reduce_ops.hpp" + +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_l2, ReduceOpsAttrTest, Type); diff --git a/ngraph/test/visitors/op/reduce_logical_and.cpp b/ngraph/test/visitors/op/reduce_logical_and.cpp index 8a5d68010e7..b460be15efc 100644 --- a/ngraph/test/visitors/op/reduce_logical_and.cpp +++ b/ngraph/test/visitors/op/reduce_logical_and.cpp @@ -2,34 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "gtest/gtest.h" +#include "reduce_ops.hpp" -#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, reduce_logical_and_op) -{ - // ReduceLogicalAnd derives visit_attributes from op::util::LogicalReductionKeepDims - NodeBuilder::get_ops().register_factory(); - auto data = make_shared(element::f32, Shape{3, 4, 5}); - auto reduction_axes = make_shared(element::i64, Shape{2}); - - bool keep_dims = true; - - auto reduce_logical_and = make_shared(data, reduction_axes, keep_dims); - NodeBuilder builder(reduce_logical_and); - auto g_reduce_logical_and = as_type_ptr(builder.create()); - - EXPECT_EQ(g_reduce_logical_and->get_keep_dims(), reduce_logical_and->get_keep_dims()); -} +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_logical_and, ReduceOpsAttrTest, Type); diff --git a/ngraph/test/visitors/op/reduce_logical_or.cpp b/ngraph/test/visitors/op/reduce_logical_or.cpp index 87fc81e36b8..265256e3a48 100644 --- a/ngraph/test/visitors/op/reduce_logical_or.cpp +++ b/ngraph/test/visitors/op/reduce_logical_or.cpp @@ -2,34 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "gtest/gtest.h" +#include "reduce_ops.hpp" -#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, reduce_logical_or_op) -{ - // ReduceLogicalOr derives visit_attributes from op::util::LogicalReductionKeepDims - NodeBuilder::get_ops().register_factory(); - auto data = make_shared(element::f32, Shape{3, 4, 5}); - auto reduction_axes = make_shared(element::i64, Shape{2}); - - bool keep_dims = true; - - auto reduce_logical_or = make_shared(data, reduction_axes, keep_dims); - NodeBuilder builder(reduce_logical_or); - auto g_reduce_logical_or = as_type_ptr(builder.create()); - - EXPECT_EQ(g_reduce_logical_or->get_keep_dims(), reduce_logical_or->get_keep_dims()); -} +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_logical_or, ReduceOpsAttrTest, Type); diff --git a/ngraph/test/visitors/op/reduce_max.cpp b/ngraph/test/visitors/op/reduce_max.cpp index 6ff4a6174ef..7cfe9b54f57 100644 --- a/ngraph/test/visitors/op/reduce_max.cpp +++ b/ngraph/test/visitors/op/reduce_max.cpp @@ -2,34 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "gtest/gtest.h" +#include "reduce_ops.hpp" -#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, reduce_max_op) -{ - // ReduceMax derives visit_attributes from op::util::ArithmeticReductionKeepDims - NodeBuilder::get_ops().register_factory(); - auto data = make_shared(element::f32, Shape{3, 4, 5}); - auto reduction_axes = make_shared(element::i64, Shape{2}); - - bool keep_dims = true; - - auto reduce_max = make_shared(data, reduction_axes, keep_dims); - NodeBuilder builder(reduce_max); - auto g_reduce_max = as_type_ptr(builder.create()); - - EXPECT_EQ(g_reduce_max->get_keep_dims(), reduce_max->get_keep_dims()); -} +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_max, ReduceOpsAttrTest, Type); diff --git a/ngraph/test/visitors/op/reduce_mean.cpp b/ngraph/test/visitors/op/reduce_mean.cpp index e8f90e3d282..2d99381f4f9 100644 --- a/ngraph/test/visitors/op/reduce_mean.cpp +++ b/ngraph/test/visitors/op/reduce_mean.cpp @@ -2,34 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "gtest/gtest.h" +#include "reduce_ops.hpp" -#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, reduce_mean_op) -{ - // ReduceMean derives visit_attributes from op::util::ArithmeticReductionKeepDims - NodeBuilder::get_ops().register_factory(); - auto data = make_shared(element::f32, Shape{3, 4, 5}); - auto reduction_axes = make_shared(element::i64, Shape{2}); - - bool keep_dims = true; - - auto reduce_mean = make_shared(data, reduction_axes, keep_dims); - NodeBuilder builder(reduce_mean); - auto g_reduce_mean = as_type_ptr(builder.create()); - - EXPECT_EQ(g_reduce_mean->get_keep_dims(), reduce_mean->get_keep_dims()); -} +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_mean, ReduceOpsAttrTest, Type); diff --git a/ngraph/test/visitors/op/reduce_min.cpp b/ngraph/test/visitors/op/reduce_min.cpp index e0972bfd28d..90dcac33ce7 100644 --- a/ngraph/test/visitors/op/reduce_min.cpp +++ b/ngraph/test/visitors/op/reduce_min.cpp @@ -2,34 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "gtest/gtest.h" +#include "reduce_ops.hpp" -#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, reduce_min_op) -{ - // ReduceMin derives visit_attributes from op::util::ArithmeticReductionKeepDims - NodeBuilder::get_ops().register_factory(); - auto data = make_shared(element::f32, Shape{3, 4, 5}); - auto reduction_axes = make_shared(element::i64, Shape{2}); - - bool keep_dims = true; - - auto reduce_min = make_shared(data, reduction_axes, keep_dims); - NodeBuilder builder(reduce_min); - auto g_reduce_min = as_type_ptr(builder.create()); - - EXPECT_EQ(g_reduce_min->get_keep_dims(), reduce_min->get_keep_dims()); -} +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_min, ReduceOpsAttrTest, Type); diff --git a/ngraph/test/visitors/op/reduce_ops.hpp b/ngraph/test/visitors/op/reduce_ops.hpp new file mode 100644 index 00000000000..dfbf1b6eba8 --- /dev/null +++ b/ngraph/test/visitors/op/reduce_ops.hpp @@ -0,0 +1,48 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" + +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" + +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +template +class ReduceOpsAttrTest : public ::testing::Test +{ +}; + +TYPED_TEST_CASE_P(ReduceOpsAttrTest); + +TYPED_TEST_P(ReduceOpsAttrTest, reduce_ops) +{ + Shape in_shape{3, 4, 5}; + element::Type in_et = element::f32; + + Shape axes_shape{2}; + element::Type axes_et = element::i64; + + bool keep_dims = true; + + NodeBuilder::get_ops().register_factory(); + auto data = make_shared(in_et, in_shape); + auto reduction_axes = make_shared(axes_et, axes_shape); + auto reduce_op = make_shared(data, reduction_axes, keep_dims); + + NodeBuilder builder(reduce_op); + const auto expected_attr_count = 1; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); + auto g_reduce_op = as_type_ptr(builder.create()); + EXPECT_EQ(g_reduce_op->get_keep_dims(), reduce_op->get_keep_dims()); +} + +REGISTER_TYPED_TEST_CASE_P( + ReduceOpsAttrTest, + reduce_ops); diff --git a/ngraph/test/visitors/op/reduce_prod.cpp b/ngraph/test/visitors/op/reduce_prod.cpp index 059186376d2..21cb8ff4fc3 100644 --- a/ngraph/test/visitors/op/reduce_prod.cpp +++ b/ngraph/test/visitors/op/reduce_prod.cpp @@ -2,34 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "gtest/gtest.h" +#include "reduce_ops.hpp" -#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, reduce_prod_op) -{ - // ReduceProd derives visit_attributes from op::util::ArithmeticReductionKeepDims - NodeBuilder::get_ops().register_factory(); - auto data = make_shared(element::f32, Shape{3, 4, 5}); - auto reduction_axes = make_shared(element::i64, Shape{2}); - - bool keep_dims = true; - - auto reduce_prod = make_shared(data, reduction_axes, keep_dims); - NodeBuilder builder(reduce_prod); - auto g_reduce_prod = as_type_ptr(builder.create()); - - EXPECT_EQ(g_reduce_prod->get_keep_dims(), reduce_prod->get_keep_dims()); -} +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_prod, ReduceOpsAttrTest, Type); diff --git a/ngraph/test/visitors/op/reduce_sum.cpp b/ngraph/test/visitors/op/reduce_sum.cpp index 46d2a73ae46..aa0414d0987 100644 --- a/ngraph/test/visitors/op/reduce_sum.cpp +++ b/ngraph/test/visitors/op/reduce_sum.cpp @@ -2,34 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "gtest/gtest.h" +#include "reduce_ops.hpp" -#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, reduce_sum_op) -{ - // ReduceSum derives visit_attributes from op::util::ArithmeticReductionKeepDims - NodeBuilder::get_ops().register_factory(); - auto data = make_shared(element::f32, Shape{3, 4, 5}); - auto reduction_axes = make_shared(element::i64, Shape{2}); - - bool keep_dims = true; - - auto reduce_sum = make_shared(data, reduction_axes, keep_dims); - NodeBuilder builder(reduce_sum); - auto g_reduce_sum = as_type_ptr(builder.create()); - - EXPECT_EQ(g_reduce_sum->get_keep_dims(), reduce_sum->get_keep_dims()); -} +using Type = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(attributes_reduce_sum, ReduceOpsAttrTest, Type); From 6e599eab6065d8cbd4d9f967d9bfed0578fcc547 Mon Sep 17 00:00:00 2001 From: Jozef Daniecki Date: Wed, 12 May 2021 05:31:19 +0200 Subject: [PATCH 16/99] Remove empty files on failed serialization (#5595) * Add unit-test for case when serialzation fail. * Delete serialization artifacts on failure. * Close file streams before file remove. * Fix typos. --- .../src/transformations/serialize.cpp | 13 +++- .../ir_serialization/cleanup.cpp | 63 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 inference-engine/tests/functional/inference_engine/ir_serialization/cleanup.cpp diff --git a/inference-engine/src/transformations/src/transformations/serialize.cpp b/inference-engine/src/transformations/src/transformations/serialize.cpp index 475d04c6d55..17695b6d6b9 100644 --- a/inference-engine/src/transformations/src/transformations/serialize.cpp +++ b/inference-engine/src/transformations/src/transformations/serialize.cpp @@ -837,7 +837,18 @@ bool pass::Serialize::run_on_function(std::shared_ptr f) { std::ofstream xml_file(m_xmlPath, std::ios::out); NGRAPH_CHECK(xml_file, "Can't open xml file: \"" + m_xmlPath + "\""); - serializeFunc(xml_file, bin_file); + try { + serializeFunc(xml_file, bin_file); + } catch (const ngraph::CheckFailure& e) { + // optimization decission was made to create .bin file upfront and + // write to it directly instead of buffering its content in memory, + // hence we need to delete it here in case of failure + xml_file.close(); + bin_file.close(); + std::remove(m_xmlPath.c_str()); + std::remove(m_binPath.c_str()); + throw; + } } // Return false because we didn't change nGraph Function diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/cleanup.cpp b/inference-engine/tests/functional/inference_engine/ir_serialization/cleanup.cpp new file mode 100644 index 00000000000..692722023c7 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/cleanup.cpp @@ -0,0 +1,63 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "common_test_utils/ngraph_test_utils.hpp" +#include "gtest/gtest.h" +#include "ie_core.hpp" +#include "ngraph_functions/builders.hpp" + +#ifndef IR_SERIALIZATION_MODELS_PATH // should be already defined by cmake +#define IR_SERIALIZATION_MODELS_PATH "" +#endif + +class SerializationCleanupTest : public CommonTestUtils::TestsCommon { +protected: + const std::string test_name = GetTestName() + "_" + GetTimestamp(); + std::string m_out_xml_path = test_name + ".xml"; + std::string m_out_bin_path = test_name + ".bin"; + + void TearDown() override { + std::remove(m_out_xml_path.c_str()); + std::remove(m_out_xml_path.c_str()); + } +}; + +namespace { +std::shared_ptr CreateTestFunction( + const std::string& name, const ngraph::PartialShape& ps) { + using namespace ngraph; + const auto param = std::make_shared(element::f16, ps); + const auto convert = std::make_shared(param, element::f32); + const auto result = std::make_shared(convert); + return std::make_shared(ResultVector{result}, + ParameterVector{param}, name); +} +} // namespace + +TEST_F(SerializationCleanupTest, SerializationShouldWork) { + const auto f = + CreateTestFunction("StaticFunction", ngraph::PartialShape{2, 2}); + + const InferenceEngine::CNNNetwork net{f}; + net.serialize(m_out_xml_path, m_out_bin_path); + + // .xml & .bin files should be present + ASSERT_TRUE(std::ifstream(m_out_xml_path, std::ios::in).good()); + ASSERT_TRUE(std::ifstream(m_out_bin_path, std::ios::in).good()); +} + +TEST_F(SerializationCleanupTest, SerializationShouldFail) { + const auto f = + CreateTestFunction("DynamicFunction", ngraph::PartialShape::dynamic()); + + const InferenceEngine::CNNNetwork net{f}; + ASSERT_THROW(net.serialize(m_out_xml_path, m_out_bin_path), + InferenceEngine::Exception); + + // .xml & .bin files shouldn't be present + ASSERT_FALSE(std::ifstream(m_out_xml_path, std::ios::in).good()); + ASSERT_FALSE(std::ifstream(m_out_bin_path, std::ios::in).good()); +} \ No newline at end of file From a78515f3e7b8a6f2e1c5e455a2c85295fdffec8b Mon Sep 17 00:00:00 2001 From: Gabriele Galiero Casay Date: Wed, 12 May 2021 08:21:33 +0200 Subject: [PATCH 17/99] Revise DeformableConvolution operation class (#5244) * Enhance dynamic shape inference of validate and infer types method * Review op class of DeformableConvolution * Add node validation checks into validate and infer types specific to element type and shape of inputs * Refactor validate and infer types method to use common function to validate conv parameters and infer output shape * Apply these changes to Convolution and BinaryConvolution for alignment * Add type_prop unit tests * Add node validation checks for deformable values spatial dimensions * Fix type_prop and python api shapes * Fix deformable values spatial dimensions * Add validation checks in reference implementation * Address review comments * Remove reference to const for basic types in ref impl * Update comment with ticket to add check for u1 * Change deformable values to offset to align with spec --- .../single_layer/deformable_convolution.cpp | 2 +- .../ngraph/op/deformable_convolution.hpp | 4 +- .../core/include/ngraph/validation_util.hpp | 9 + .../reference/deformable_convolution.hpp | 68 +- ngraph/core/src/op/binary_convolution.cpp | 12 +- ngraph/core/src/op/convolution.cpp | 10 + ngraph/core/src/op/deformable_convolution.cpp | 252 ++-- ngraph/core/src/validation_util.cpp | 82 +- .../tests/test_ngraph/test_create_op.py | 2 +- .../test/type_prop/deformable_convolution.cpp | 1106 +++++++++++++++-- 10 files changed, 1282 insertions(+), 265 deletions(-) diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/deformable_convolution.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/deformable_convolution.cpp index 99b6f398d5f..a73f583f8b8 100644 --- a/inference-engine/tests/functional/inference_engine/serialization/single_layer/deformable_convolution.cpp +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/deformable_convolution.cpp @@ -16,7 +16,7 @@ TEST_P(DeformableConvolutionLayerTest, Serialize) { const std::vector netPrecisions = { InferenceEngine::Precision::FP32, InferenceEngine::Precision::FP16, InferenceEngine::Precision::I32, InferenceEngine::Precision::I16}; -const std::vector> offsets = {{1, 18, 28, 28}}; +const std::vector> offsets = {{1, 18, 26, 26}}; const std::vector> filters = {{1, 1, 3, 3}}; const std::vector> strides = {{1, 1}}; const std::vector> padBegins = {{0, 0}}; diff --git a/ngraph/core/include/ngraph/op/deformable_convolution.hpp b/ngraph/core/include/ngraph/op/deformable_convolution.hpp index 7ed84915456..8a62337a610 100644 --- a/ngraph/core/include/ngraph/op/deformable_convolution.hpp +++ b/ngraph/core/include/ngraph/op/deformable_convolution.hpp @@ -25,7 +25,7 @@ namespace ngraph /// \brief Constructs a conversion operation. /// /// \param arg Node that produces the input tensor. - /// \param deformable_values Node producing the deformable values tensor. + /// \param offsets Node producing the deformable values tensor. /// \param filters Node producing the filters(kernels) tensor with OIZYX /// layout. /// \param strides Convolution strides. @@ -44,7 +44,7 @@ namespace ngraph /// \param deformable_group The number of groups which deformable values and /// output should be split into along the channel axis. DeformableConvolution(const Output& arg, - const Output& deformable_values, + const Output& offsets, const Output& filters, const Strides& strides, const CoordinateDiff& pads_begin, diff --git a/ngraph/core/include/ngraph/validation_util.hpp b/ngraph/core/include/ngraph/validation_util.hpp index bfac7306ccb..353763ab29e 100644 --- a/ngraph/core/include/ngraph/validation_util.hpp +++ b/ngraph/core/include/ngraph/validation_util.hpp @@ -35,6 +35,14 @@ namespace ngraph bool is_window_all_in_padding_allowed, bool ceil_mode = false); + void validate_conv_params_spatial_dimensions(const Node* node, + const size_t num_spatial_dims, + const op::PadType auto_pad, + Strides& strides, + Strides& dilations, + CoordinateDiff& pads_begin, + CoordinateDiff& pads_end); + /// \brief Validates input shape ranks and infers convolution forward output shape. /// /// \param[in] node Node with convolution operation. @@ -49,6 +57,7 @@ namespace ngraph /// \return Partial shape of the output. PartialShape validate_and_infer_convolution_forward_output_shape(const Node* node, + const Rank& result_ps_rank, const PartialShape& data_batch_pshape, const PartialShape& filters_pshape, const op::PadType auto_pad, diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/deformable_convolution.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/deformable_convolution.hpp index d2a9e867f8e..c6ee668fbe0 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/deformable_convolution.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/deformable_convolution.hpp @@ -14,31 +14,53 @@ namespace ngraph { namespace def_conv_impl { - inline void validate_params(const Shape& in_shape, - const Shape& o_shape, - const Shape& f_shape, - const Strides& strides, - const Strides& dilations, - const CoordinateDiff& pads_begin, - const CoordinateDiff& pads_end) + inline void validate_deformable_convolution_params(const Shape& in_shape, + const Shape& o_shape, + const Shape& f_shape, + const Shape& out_shape, + const Strides& strides, + const Strides& dilations, + const CoordinateDiff& pads_begin, + const CoordinateDiff& pads_end, + const int64_t groups, + const int64_t deformable_groups) { // this implementation supports 2D deformable convolutions NGRAPH_CHECK(in_shape.size() == 4, "Unsupported input rank: ", in_shape); - NGRAPH_CHECK(o_shape.size() == 4, "Unsupported offset rank: ", o_shape); - NGRAPH_CHECK(f_shape.size() == 4, "Unsupported kernel rank: ", f_shape); - const auto spatial_dims = in_shape.size() - 2; - NGRAPH_CHECK(strides.size() == spatial_dims, - "Strides not definied for all and only spatial dimensions"); + NGRAPH_CHECK(in_shape[1] % groups == 0, + "Input channels of data batch input must be evenly divisible by " + "'groups' attribute"); + NGRAPH_CHECK(f_shape[0] % groups == 0, + "Output channels of filters must be evenly divisible by 'groups' " + "attribute"); - NGRAPH_CHECK(dilations.size() == spatial_dims, - "Dilations not defined for all and only spatial dimensions"); + const Shape scaled_f_shape = [f_shape](int64_t g) { + Shape shape{f_shape}; + shape[1] *= g; + return shape; + }(groups); - NGRAPH_CHECK((pads_begin.size() == pads_end.size()) && - (pads_begin.size() == spatial_dims), - "Pads not defined for all and only spatial dimensions"); + validate_convolution_parameters(in_shape, + scaled_f_shape, + out_shape, + strides, + dilations, + pads_begin, + pads_end); + + const Shape f_spatial_shape{std::next(f_shape.begin(), 2), std::end(f_shape)}; + const Shape o_spatial_shape{std::next(o_shape.begin(), 2), std::end(o_shape)}; + const Shape out_spatial_shape{std::next(out_shape.begin(), 2), + std::end(out_shape)}; + + NGRAPH_CHECK(o_shape[1] == deformable_groups * shape_size(f_spatial_shape) * 2, + "The channels dimension of offsets input is not " + "compatible with filters and 'deformable group' attribute"); + NGRAPH_CHECK(out_spatial_shape == o_spatial_shape, + "Spatial dimensions of output and offsets values must be equal"); } inline Shape shape_reduce(const Shape& s) { return Shape(++s.begin(), s.end()); } @@ -176,8 +198,16 @@ namespace ngraph { using namespace def_conv_impl; - validate_params( - in_shape, o_shape, f_shape, strides, dilation, pads_begin, pads_end); + validate_deformable_convolution_params(in_shape, + o_shape, + f_shape, + out_shape, + strides, + dilation, + pads_begin, + pads_end, + groups, + deformable_groups); // here we are converting all param types to int's to avoid arithmetic issues // (e.g signed + unsigned) in indexes calculation later diff --git a/ngraph/core/src/op/binary_convolution.cpp b/ngraph/core/src/op/binary_convolution.cpp index 8460eee543d..57ce4b9b222 100644 --- a/ngraph/core/src/op/binary_convolution.cpp +++ b/ngraph/core/src/op/binary_convolution.cpp @@ -71,10 +71,20 @@ void op::v1::BinaryConvolution::validate_and_infer_types() data_batch_et); // TODO: Add NodeValidationCheck to filters et once u1 is supported in nGraph Python API - // (#49517) + // (#52715) + + Rank result_ps_rank; + NODE_VALIDATION_CHECK( + this, + Rank::merge(result_ps_rank, data_batch_pshape.rank(), filters_pshape.rank()), + "Data batch and filters inputs must have same rank. Got: ", + data_batch_pshape, + " and ", + filters_pshape); PartialShape result_shape = validate_and_infer_convolution_forward_output_shape(this, + result_ps_rank, data_batch_pshape, filters_pshape, m_auto_pad, diff --git a/ngraph/core/src/op/convolution.cpp b/ngraph/core/src/op/convolution.cpp index b0afc7f4346..667fa933046 100644 --- a/ngraph/core/src/op/convolution.cpp +++ b/ngraph/core/src/op/convolution.cpp @@ -67,8 +67,18 @@ void op::v1::Convolution::validate_and_infer_types() "Element types must be numeric. Got: ", result_et); + Rank result_ps_rank; + NODE_VALIDATION_CHECK( + this, + Rank::merge(result_ps_rank, data_batch_pshape.rank(), filters_pshape.rank()), + "Data batch and filters inputs must have same rank. Got: ", + data_batch_pshape, + " and ", + filters_pshape); + PartialShape result_shape = validate_and_infer_convolution_forward_output_shape(this, + result_ps_rank, data_batch_pshape, filters_pshape, m_auto_pad, diff --git a/ngraph/core/src/op/deformable_convolution.cpp b/ngraph/core/src/op/deformable_convolution.cpp index eb5071af7de..5893a33a928 100644 --- a/ngraph/core/src/op/deformable_convolution.cpp +++ b/ngraph/core/src/op/deformable_convolution.cpp @@ -16,7 +16,7 @@ using namespace ngraph; constexpr NodeTypeInfo op::v1::DeformableConvolution::type_info; op::v1::DeformableConvolution::DeformableConvolution(const Output& arg, - const Output& deformable_values, + const Output& offsets, const Output& filters, const Strides& strides, const CoordinateDiff& pads_begin, @@ -25,7 +25,7 @@ op::v1::DeformableConvolution::DeformableConvolution(const Output& arg, const PadType& auto_pad, const int64_t group, const int64_t deformable_group) - : Op({arg, deformable_values, filters}) + : Op({arg, offsets, filters}) , m_strides(strides) , m_dilations(dilations) , m_pads_begin(pads_begin) @@ -53,139 +53,171 @@ bool op::v1::DeformableConvolution::visit_attributes(AttributeVisitor& visitor) void op::v1::DeformableConvolution::validate_and_infer_types() { NGRAPH_OP_SCOPE(v1_DeformableConvolution_validate_and_infer_types); - const PartialShape& data_batch_shape = get_input_partial_shape(0); - const PartialShape& deformable_values_shape = get_input_partial_shape(1); - const PartialShape& filters_shape = get_input_partial_shape(2); + const PartialShape& data_batch_pshape = get_input_partial_shape(0); + const PartialShape& offsets_pshape = get_input_partial_shape(1); + const PartialShape& filters_pshape = get_input_partial_shape(2); element::Type data_batch_et = get_input_element_type(0); + element::Type offsets_et = get_input_element_type(1); element::Type filters_et = get_input_element_type(2); - if (deformable_values_shape.rank().is_static()) + element::Type result_et; + NODE_VALIDATION_CHECK(this, + element::Type::merge(result_et, data_batch_et, offsets_et) && + element::Type::merge(result_et, result_et, filters_et), + "Element types of inputs do not match. Got: data batch (", + data_batch_et, + "), offsets (", + offsets_et, + ") and filters (", + filters_et, + ")"); + + NODE_VALIDATION_CHECK(this, + result_et.is_real() || result_et.is_integral_number(), + "Element type of inputs must be numeric. Got: ", + result_et); + + Rank result_ps_rank{}; + NODE_VALIDATION_CHECK( + this, + Rank::merge(result_ps_rank, data_batch_pshape.rank(), offsets_pshape.rank()) && + Rank::merge(result_ps_rank, result_ps_rank, filters_pshape.rank()), + "Ranks of inputs do not match. Got: data batch shape ", + data_batch_pshape, + ", offsets shape ", + offsets_pshape, + ", filters shape ", + filters_pshape); + + NODE_VALIDATION_CHECK( + this, result_ps_rank.compatible(4), "Inputs must be of rank 4. Got: ", result_ps_rank); + + NODE_VALIDATION_CHECK( + this, m_group > 0, "Attribute 'group' must be any value starting from 1. Got: ", m_group); + + NODE_VALIDATION_CHECK(this, + m_deformable_group > 0, + "Attribute 'deformable group' must be any value starting from 1. Got: ", + m_deformable_group); + + if (offsets_pshape.rank().is_static()) { - NODE_VALIDATION_CHECK( - this, - deformable_values_shape.rank().get_length() >= 3u, - "The deformable values tensor rank is expected to be at least 3, got: ", - deformable_values_shape.rank()); + if (offsets_pshape[1].is_static()) + { + if (filters_pshape.rank().is_static() && filters_pshape[2].is_static() && + filters_pshape[3].is_static()) + { + auto offsets_channels = m_deformable_group * filters_pshape[2].get_length() * + filters_pshape[3].get_length() * 2; + NODE_VALIDATION_CHECK(this, + offsets_pshape[1].get_length() == offsets_channels, + "The channels dimension of offsets input is not " + "compatible with filters and 'deformable group' attribute. " + "Offsets input shape: ", + offsets_pshape, + ", deformable 'group' attribute value: ", + m_deformable_group, + ", filters shape: ", + filters_pshape); + } + else + { + // At least we can check if offsets channels is evenly divisible by deformable + // group attribute + NODE_VALIDATION_CHECK(this, + offsets_pshape[1].get_length() % m_deformable_group == 0, + "The channels dimension of offsets input must be " + "evenly divisible by the 'deformable group' value along the " + "channels axis. Offsets input shape: ", + offsets_pshape, + ", 'deformable group' attribute value: ", + m_deformable_group); + } + } + + if (data_batch_pshape.rank().is_static()) + { + NODE_VALIDATION_CHECK( + this, + offsets_pshape[0].compatible(data_batch_pshape[0]), + "Data batch and offsets batch dimension must be same value. Got: ", + offsets_pshape[0], + " and ", + data_batch_pshape[0]); + } } - if (m_group > 1 && data_batch_shape[1].is_static() && filters_shape[0].is_static()) + if (data_batch_pshape.rank().is_static() && data_batch_pshape[1].is_static()) { NODE_VALIDATION_CHECK(this, - data_batch_shape[1].get_length() % m_group == 0, + data_batch_pshape[1].get_length() % m_group == 0, "The input data shape must be evenly divisible by the 'group' value " "along the channels axis. Current input shape: ", - data_batch_shape, + data_batch_pshape, ", 'group' attribute value: ", m_group); + } + if (filters_pshape.rank().is_static() && filters_pshape[0].is_static()) + { NODE_VALIDATION_CHECK( this, - filters_shape[0].get_length() % m_group == 0, - "The weights shape must be evenly divisible by the 'group' value along " - "the channels axis. Current weights shape: ", - filters_shape, + filters_pshape[0].get_length() % m_group == 0, + "The filters shape must be evenly divisible by the 'group' value along " + "the channels axis. Current filters shape: ", + filters_pshape, ", 'group' attribute value: ", m_group); } - if (m_deformable_group > 1 && deformable_values_shape[1].is_static()) - { - NODE_VALIDATION_CHECK(this, - deformable_values_shape[1].get_length() % m_deformable_group == 0, - "The deformable values input must be evenly divisible by the " - "'deformable group' value " - "along the channels axis. Current input shape: ", - deformable_values_shape, - ", 'deformable group' attribute value: ", - m_deformable_group); - } - - element::Type result_et; - NODE_VALIDATION_CHECK( - this, - element::Type::merge(result_et, data_batch_et, filters_et), - "Element types for data batch and filters do not match (data batch element type: ", - data_batch_et, - ", filters element type: ", - filters_et, - ")."); - - PartialShape result_shape = PartialShape::dynamic(); - if (data_batch_shape.rank().is_static()) - { - result_shape = - std::vector(data_batch_shape.rank().get_length(), Dimension::dynamic()); - - if (data_batch_shape.rank().get_length() > 1) - { - result_shape[0] = data_batch_shape[0]; // batch size - } - - if (filters_shape.rank().is_static() && filters_shape.rank().get_length() > 1) - { - result_shape[1] = filters_shape[0]; // filter channel size - } - } - - if (m_strides.size() == 0) - { - m_strides = conv_default_strides(this, data_batch_shape, filters_shape); - } - - if (m_dilations.size() == 0) - { - m_dilations = conv_default_strides(this, data_batch_shape, filters_shape); - } - - if (m_pads_begin.size() == 0) - { - m_pads_begin = conv_default_padding(this, data_batch_shape, filters_shape); - } - - if (m_pads_end.size() == 0) - { - m_pads_end = conv_default_padding(this, data_batch_shape, filters_shape); - } - - if (m_auto_pad == PadType::SAME_UPPER || m_auto_pad == PadType::SAME_LOWER) - { - bool auto_padding_applied = false; - if (filters_shape.is_static()) - { - m_pads_begin.clear(); - m_pads_end.clear(); - auto filter_shape = filters_shape.to_shape(); - filter_shape.erase(filter_shape.begin(), filter_shape.begin() + 2); // Remove {O,I} - auto_padding_applied = try_apply_auto_padding(data_batch_shape, - filter_shape, - m_strides, - m_dilations, - m_auto_pad, - m_pads_end, - m_pads_begin); - } - if (!auto_padding_applied) - { - set_output_type(0, data_batch_et, result_shape); - return; - } - } // adjust filter shape to reuse regular infer_convolution_forward() const auto new_filters_pshape = [&](int groups) { - auto new_shape(filters_shape); - new_shape[1] *= groups; + auto new_shape(filters_pshape); + if (new_shape.rank().is_static()) + { + new_shape[1] *= groups; + } return new_shape; }(m_group); - result_shape = infer_convolution_forward(this, - data_batch_shape, - Strides(m_strides.size(), 1), // dummy data dilations - m_pads_begin, - m_pads_end, - new_filters_pshape, - m_strides, - m_dilations); + PartialShape result_shape = + validate_and_infer_convolution_forward_output_shape(this, + result_ps_rank, + data_batch_pshape, + new_filters_pshape, + m_auto_pad, + m_strides, + m_dilations, + m_pads_begin, + m_pads_end); + if (result_shape.rank().is_static() && offsets_pshape.rank().is_static()) + { + PartialShape result_spatial_shape = [&result_shape]() { + vector result_spatial_dims{result_shape}; + result_spatial_dims.erase(result_spatial_dims.begin(), result_spatial_dims.begin() + 2); + return PartialShape{result_spatial_dims}; + }(); + + PartialShape offsets_spatial_shape = [&offsets_pshape]() { + vector offsets_spatial_dims{offsets_pshape}; + offsets_spatial_dims.erase(offsets_spatial_dims.begin(), + offsets_spatial_dims.begin() + 2); + return PartialShape{offsets_spatial_dims}; + }(); + + NODE_VALIDATION_CHECK(this, + offsets_spatial_shape.compatible(result_spatial_shape), + "Spatial dimensions of offsets and output must be equal. Got: ", + offsets_spatial_shape, + " and ", + result_spatial_shape); + + if (result_shape[0].is_dynamic()) + { + result_shape[0] = offsets_pshape[0]; // batch size + } + } set_output_type(0, result_et, result_shape); } diff --git a/ngraph/core/src/validation_util.cpp b/ngraph/core/src/validation_util.cpp index 7678a9f76eb..2abb3eaf0ec 100644 --- a/ngraph/core/src/validation_util.cpp +++ b/ngraph/core/src/validation_util.cpp @@ -224,8 +224,45 @@ PartialShape ngraph::infer_windowed_reduction_output_shape(const Node* node, return output_shape; } +void ngraph::validate_conv_params_spatial_dimensions(const Node* node, + const size_t num_spatial_dims, + const op::PadType auto_pad, + Strides& strides, + Strides& dilations, + CoordinateDiff& pads_begin, + CoordinateDiff& pads_end) +{ + if (strides.size() == 0) + { + strides = Strides(num_spatial_dims, 1); + } + if (dilations.size() == 0) + { + dilations = Strides(num_spatial_dims, 1); + } + if (pads_begin.size() == 0 || auto_pad == op::PadType::VALID) + { + pads_begin = CoordinateDiff(num_spatial_dims, 0); + } + if (pads_end.size() == 0 || auto_pad == op::PadType::VALID) + { + pads_end = CoordinateDiff(num_spatial_dims, 0); + } + NODE_VALIDATION_CHECK(node, + strides.size() == num_spatial_dims, + "Strides should be defined for all and only spatial features."); + NODE_VALIDATION_CHECK(node, + dilations.size() == num_spatial_dims, + "Dilations should be defined for all and only spatial features."); + NODE_VALIDATION_CHECK(node, + pads_begin.size() == num_spatial_dims && + pads_end.size() == num_spatial_dims, + "Pads should be defined for all and only spatial features."); +} + PartialShape ngraph::validate_and_infer_convolution_forward_output_shape( const Node* node, + const Rank& result_ps_rank, const PartialShape& data_batch_pshape, const PartialShape& filters_pshape, const op::PadType auto_pad, @@ -234,51 +271,12 @@ PartialShape ngraph::validate_and_infer_convolution_forward_output_shape( CoordinateDiff& pads_begin, CoordinateDiff& pads_end) { - Rank result_ps_rank; - NODE_VALIDATION_CHECK( - node, - Rank::merge(result_ps_rank, data_batch_pshape.rank(), filters_pshape.rank()), - "Data batch and filters inputs must have same rank. Got: ", - data_batch_pshape, - " and ", - filters_pshape); - PartialShape result_shape = PartialShape::dynamic(); if (result_ps_rank.is_static()) { - const size_t num_spatial_dims = result_ps_rank.get_length() - 2; - if (strides.size() == 0) - { - strides = Strides(num_spatial_dims, 1); - } - - if (dilations.size() == 0) - { - dilations = Strides(num_spatial_dims, 1); - } - - if (pads_begin.size() == 0 || auto_pad == op::PadType::VALID) - { - pads_begin = CoordinateDiff(num_spatial_dims, 0); - } - - if (pads_end.size() == 0 || auto_pad == op::PadType::VALID) - { - pads_end = CoordinateDiff(num_spatial_dims, 0); - } - - NODE_VALIDATION_CHECK(node, - strides.size() == num_spatial_dims, - "Strides should be defined for all and only spatial features."); - - NODE_VALIDATION_CHECK(node, - dilations.size() == num_spatial_dims, - "Dilations should be defined for all and only spatial features."); - - NODE_VALIDATION_CHECK(node, - pads_begin.size() == num_spatial_dims && - pads_end.size() == num_spatial_dims, - "Pads should be defined for all and only spatial features."); + const auto num_spatial_dims = result_ps_rank.get_length() - 2; + validate_conv_params_spatial_dimensions( + node, num_spatial_dims, auto_pad, strides, dilations, pads_begin, pads_end); result_shape = PartialShape::dynamic(result_ps_rank); if (data_batch_pshape.rank().is_static()) diff --git a/ngraph/python/tests/test_ngraph/test_create_op.py b/ngraph/python/tests/test_ngraph/test_create_op.py index a14c7fc8d36..7d430782e42 100644 --- a/ngraph/python/tests/test_ngraph/test_create_op.py +++ b/ngraph/python/tests/test_ngraph/test_create_op.py @@ -112,7 +112,7 @@ def test_deformable_convolution(dtype): dilations = np.array([1, 1]) input0_shape = [1, 1, 9, 9] - input1_shape = [1, 1, 9, 9] + input1_shape = [1, 18, 7, 7] input2_shape = [1, 1, 3, 3] expected_shape = [1, 1, 7, 7] diff --git a/ngraph/test/type_prop/deformable_convolution.cpp b/ngraph/test/type_prop/deformable_convolution.cpp index ee5d94ceec7..bed13263dc9 100644 --- a/ngraph/test/type_prop/deformable_convolution.cpp +++ b/ngraph/test/type_prop/deformable_convolution.cpp @@ -9,11 +9,13 @@ using namespace std; using namespace ngraph; -TEST(type_prop, deformable_conv_v1_partial_auto_padding_same) +TEST(type_prop, deformable_convolution_partial_auto_padding_same) { - const PartialShape data_batch_shape{1, 8, 5, 5}; - const PartialShape deformable_shape{1, 4, 3, 3}; - const PartialShape filters_shape{4, 2, 3, 3}; + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 36, 5, 5}; + const PartialShape filters_pshape{4, 1, 3, 3}; + const element::Type_t et = element::f32; + Strides strides{1, 1}; CoordinateDiff pads_begin{0, 0}; CoordinateDiff pads_end{0, 0}; @@ -22,12 +24,11 @@ TEST(type_prop, deformable_conv_v1_partial_auto_padding_same) const int64_t group = 4; const int64_t deformable_group = 2; - auto data_batch = make_shared(element::f32, data_batch_shape); - auto deformable_values = make_shared(element::f32, deformable_shape); - auto filters = make_shared(element::f32, filters_shape); - + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); auto deformable_conv = make_shared(data_batch, - deformable_values, + offsets, filters, strides, pads_begin, @@ -42,11 +43,13 @@ TEST(type_prop, deformable_conv_v1_partial_auto_padding_same) ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{1, 1})); } -TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_nc_dims_dynamic_same_lower) +TEST(type_prop, deformable_convolution_partial_auto_padding_same_lower_data_batch_nc_dims_dynamic) { - const PartialShape data_batch_shape{Dimension::dynamic(), Dimension::dynamic(), 5, 5}; - const PartialShape deformable_shape{1, 4, 3, 3}; - const PartialShape filters_shape{4, 4, 3, 3}; + const PartialShape data_batch_pshape{Dimension::dynamic(), Dimension::dynamic(), 5, 5}; + const PartialShape offsets_pshape{Dimension::dynamic(), 36, 5, 5}; + const PartialShape filters_pshape{4, 4, 3, 3}; + const element::Type_t et = element::f32; + Strides strides{1, 1}; CoordinateDiff pads_begin{0, 0}; CoordinateDiff pads_end{0, 0}; @@ -55,12 +58,11 @@ TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_nc_dims_dynamic_sam const int64_t group = 4; const int64_t deformable_group = 2; - auto data_batch = make_shared(element::f32, data_batch_shape); - auto deformable_values = make_shared(element::f32, deformable_shape); - auto filters = make_shared(element::f32, filters_shape); - + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); auto deformable_conv = make_shared(data_batch, - deformable_values, + offsets, filters, strides, pads_begin, @@ -76,11 +78,13 @@ TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_nc_dims_dynamic_sam ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{1, 1})); } -TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_nc_dims_dynamic_same_upper) +TEST(type_prop, deformable_convolution_partial_auto_padding_same_upper_data_batch_nc_dims_dynamic) { - const PartialShape data_batch_shape{Dimension::dynamic(), Dimension::dynamic(), 5, 5}; - const PartialShape deformable_shape{1, 4, 2, 2}; - const PartialShape filters_shape{4, 4, 2, 2}; + const PartialShape data_batch_pshape{Dimension::dynamic(), Dimension::dynamic(), 5, 5}; + const PartialShape offsets_pshape{1, 16, 5, 5}; + const PartialShape filters_pshape{4, 4, 2, 2}; + const element::Type_t et = element::f32; + Strides strides{1, 1}; CoordinateDiff pads_begin{0, 0}; CoordinateDiff pads_end{0, 0}; @@ -89,12 +93,11 @@ TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_nc_dims_dynamic_sam const int64_t group = 4; const int64_t deformable_group = 2; - auto data_batch = make_shared(element::f32, data_batch_shape); - auto deformable_values = make_shared(element::f32, deformable_shape); - auto filters = make_shared(element::f32, filters_shape); - + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); auto deformable_conv = make_shared(data_batch, - deformable_values, + offsets, filters, strides, pads_begin, @@ -104,17 +107,18 @@ TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_nc_dims_dynamic_sam group, deformable_group); - ASSERT_TRUE(deformable_conv->get_output_partial_shape(0).same_scheme( - PartialShape{Dimension::dynamic(), 4, 5, 5})); + ASSERT_TRUE(deformable_conv->get_output_partial_shape(0).same_scheme(PartialShape{1, 4, 5, 5})); ASSERT_EQ(deformable_conv->get_pads_begin(), (CoordinateDiff{0, 0})); ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{1, 1})); } -TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_spatial_dims_dynamic) +TEST(type_prop, deformable_convolution_partial_auto_padding_same_spatial_dims_dynamic) { - const PartialShape data_batch_shape{1, 8, Dimension::dynamic(), 5}; - const PartialShape deformable_shape{1, 4, 3, 3}; - const PartialShape filters_shape{4, 2, 3, 3}; + const PartialShape data_batch_pshape{1, 4, Dimension::dynamic(), 5}; + const PartialShape offsets_pshape{1, 36, 5, 5}; + const PartialShape filters_pshape{4, 1, 3, 3}; + const element::Type_t et = element::f32; + Strides strides{1, 1}; CoordinateDiff pads_begin{0, 0}; CoordinateDiff pads_end{0, 0}; @@ -123,12 +127,11 @@ TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_spatial_dims_dynami const int64_t group = 4; const int64_t deformable_group = 2; - auto data_batch = make_shared(element::f32, data_batch_shape); - auto deformable_values = make_shared(element::f32, deformable_shape); - auto filters = make_shared(element::f32, filters_shape); - + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); auto deformable_conv = make_shared(data_batch, - deformable_values, + offsets, filters, strides, pads_begin, @@ -144,82 +147,1007 @@ TEST(type_prop, deformable_conv_v1_partial_auto_padding_same_spatial_dims_dynami ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{0, 1})); } -TEST(type_prop, deformable_conv_incorrect_group) +TEST(type_prop, deformable_convolution_data_batch_dynamic) { - const PartialShape data_batch_shape{1, 3, 96, 96}; - const PartialShape deformable_values_shape{1, 50, 5, 5}; - const PartialShape filters_shape{4, 3, 5, 5}; + const PartialShape data_batch_pshape{PartialShape::dynamic()}; + const PartialShape offsets_pshape{2, 36, 5, 5}; + const PartialShape filters_pshape{4, 4, 3, 3}; + const element::Type_t et = element::f32; - auto param0 = make_shared(element::f32, data_batch_shape); - auto param1 = make_shared(element::f32, deformable_values_shape); - auto param2 = make_shared(element::f32, filters_shape); + const auto auto_pad = op::PadType::EXPLICIT; + const int64_t group = 2; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}, + auto_pad, + group, + deformable_group); + + ASSERT_EQ(deformable_conv->get_auto_pad(), op::PadType::EXPLICIT); + ASSERT_EQ(deformable_conv->get_strides(), (Strides{1, 1})); + ASSERT_EQ(deformable_conv->get_dilations(), (Strides{1, 1})); + ASSERT_EQ(deformable_conv->get_pads_begin(), (CoordinateDiff{0, 0})); + ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{0, 0})); + ASSERT_TRUE(deformable_conv->get_output_partial_shape(0).same_scheme( + PartialShape{2, 4, Dimension::dynamic(), Dimension::dynamic()})); +} + +TEST(type_prop, deformable_convolution_offsets_dynamic) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{PartialShape::dynamic()}; + const PartialShape filters_pshape{4, 2, 3, 3}; + const element::Type_t et = element::f32; + + const auto auto_pad = op::PadType::SAME_LOWER; + const int64_t group = 2; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}, + auto_pad, + group, + deformable_group); + + ASSERT_EQ(deformable_conv->get_auto_pad(), op::PadType::SAME_LOWER); + ASSERT_EQ(deformable_conv->get_strides(), (Strides{1, 1})); + ASSERT_EQ(deformable_conv->get_dilations(), (Strides{1, 1})); + ASSERT_EQ(deformable_conv->get_pads_begin(), (CoordinateDiff{1, 1})); + ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{1, 1})); + ASSERT_TRUE(deformable_conv->get_output_partial_shape(0).same_scheme(PartialShape{1, 4, 5, 5})); +} + +TEST(type_prop, deformable_convolution_auto_pad_same_filters_dynamic) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 36, 3, 3}; + const PartialShape filters_pshape{PartialShape::dynamic()}; + const element::Type_t et = element::f32; + + const auto auto_pad = op::PadType::SAME_UPPER; + const int64_t group = 2; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}, + auto_pad, + group, + deformable_group); + + ASSERT_EQ(deformable_conv->get_auto_pad(), op::PadType::SAME_UPPER); + ASSERT_EQ(deformable_conv->get_strides(), (Strides{1, 1})); + ASSERT_EQ(deformable_conv->get_dilations(), (Strides{1, 1})); + ASSERT_EQ(deformable_conv->get_pads_begin(), (CoordinateDiff{0, 0})); + ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{0, 0})); + ASSERT_TRUE(deformable_conv->get_output_partial_shape(0).same_scheme( + PartialShape{1, Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()})); +} + +TEST(type_prop, deformable_convolution_deformable_data_batch_and_filters_dynamic) +{ + const PartialShape data_batch_pshape{PartialShape::dynamic()}; + const PartialShape offsets_pshape{1, 36, 3, 3}; + const PartialShape filters_pshape{PartialShape::dynamic()}; + const element::Type_t et = element::f32; + + const auto auto_pad = op::PadType::EXPLICIT; + const int64_t group = 2; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}, + auto_pad, + group, + deformable_group); + + ASSERT_EQ(deformable_conv->get_auto_pad(), op::PadType::EXPLICIT); + ASSERT_EQ(deformable_conv->get_strides(), (Strides{1, 1})); + ASSERT_EQ(deformable_conv->get_dilations(), (Strides{1, 1})); + ASSERT_EQ(deformable_conv->get_pads_begin(), (CoordinateDiff{0, 0})); + ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{0, 0})); + ASSERT_TRUE(deformable_conv->get_output_partial_shape(0).same_scheme( + PartialShape{1, Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()})); +} + +TEST(type_prop, deformable_convolution_deformable_all_inputs_dynamic) +{ + const PartialShape dyn_pshape{PartialShape::dynamic()}; + const element::Type_t et = element::f32; + + const auto auto_pad = op::PadType::EXPLICIT; + const int64_t group = 2; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, dyn_pshape); + auto offsets = make_shared(et, dyn_pshape); + auto filters = make_shared(et, dyn_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}, + auto_pad, + group, + deformable_group); + + ASSERT_EQ(deformable_conv->get_auto_pad(), op::PadType::EXPLICIT); + ASSERT_EQ(deformable_conv->get_strides(), (Strides{})); + ASSERT_EQ(deformable_conv->get_dilations(), (Strides{})); + ASSERT_EQ(deformable_conv->get_pads_begin(), (CoordinateDiff{})); + ASSERT_EQ(deformable_conv->get_pads_end(), (CoordinateDiff{})); + ASSERT_TRUE(deformable_conv->get_output_partial_shape(0).same_scheme(PartialShape::dynamic())); +} + +TEST(type_prop, deformable_convolution_invalid_et_inputs) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 4, 3, 3}; + const PartialShape filters_pshape{4, 4, 3, 3}; + + element::Type_t float_et = element::f32; + element::Type_t boolean_et = element::boolean; try { - make_shared(param0, - param1, - param2, - Strides{}, - CoordinateDiff{}, - CoordinateDiff{}, - Strides{}, - op::PadType::EXPLICIT, - 2); - - FAIL() << "DeformableConvolution created with incorrect 'group' value"; + auto data_batch = make_shared(element::f16, data_batch_pshape); + auto offsets = make_shared(float_et, offsets_pshape); + auto filters = make_shared(float_et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // data batch input must be of same element type as filters and deformable values + FAIL() << "Invalid element type of inputs not detected"; } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), "input data shape must be evenly divisible"); + EXPECT_HAS_SUBSTRING(error.what(), + "Element types of inputs do not match. Got: data batch (f16), " + "offsets (f32) and filters (f32)"); + } + catch (...) + { + FAIL() << "Element types of inputs validation check failed for unexpected reason."; } try { - make_shared(param0, - param1, - param2, - Strides{}, - CoordinateDiff{}, - CoordinateDiff{}, - Strides{}, - op::PadType::EXPLICIT, - 3); - - FAIL() << "DeformableConvolution created with incorrect 'group' value"; + auto data_batch = make_shared(float_et, data_batch_pshape); + auto offsets = make_shared(float_et, offsets_pshape); + auto filters = make_shared(element::f16, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // filters input must be of same element type as data batch and deformable values + FAIL() << "Invalid element type of inputs not detected"; } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), "weights shape must be evenly divisible"); + EXPECT_HAS_SUBSTRING(error.what(), "Element types of inputs do not match. Got: " + "data batch (f32), offsets (f32) and filters (f16)"); + } + catch (...) + { + FAIL() << "Element types of inputs validation check failed for unexpected reason."; + } + + try + { + auto data_batch = make_shared(float_et, data_batch_pshape); + auto offsets = make_shared(element::f16, offsets_pshape); + auto filters = make_shared(float_et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // deformable values input must be of same element type as data batch and filters + FAIL() << "Invalid element type of inputs not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Element types of inputs do not match. Got: data batch (f32), " + "offsets (f16) and filters (f32)"); + } + catch (...) + { + FAIL() << "Element types of inputs validation check failed for unexpected reason."; + } + + try + { + auto data_batch = make_shared(boolean_et, data_batch_pshape); + auto offsets = make_shared(boolean_et, offsets_pshape); + auto filters = make_shared(boolean_et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // element types for inputs must be numeric + FAIL() << "Invalid boolean element type of inputs not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Element type of inputs must be numeric"); + } + catch (...) + { + FAIL() << "Numeric element types of inputs validation check failed for " + "unexpected reason."; } } -TEST(type_prop, deformable_conv_incorrect_deformable_group) +TEST(type_prop, deformable_convolution_invalid_input_ranks) { - const PartialShape data_batch_shape{1, 3, 96, 96}; - const PartialShape deformable_values_shape{1, 50, 5, 5}; - const PartialShape filters_shape{3, 3, 5, 5}; - - auto param0 = make_shared(element::f32, data_batch_shape); - auto param1 = make_shared(element::f32, deformable_values_shape); - auto param2 = make_shared(element::f32, filters_shape); + const element::Type_t et = element::f32; + // data batch shape provides is rank 5 try { - make_shared(param0, - param1, - param2, - Strides{}, - CoordinateDiff{}, - CoordinateDiff{}, - Strides{}, - op::PadType::EXPLICIT, - 1, - 7); + const PartialShape data_batch_pshape{1, 4, 5, 5, 5}; + const PartialShape offsets_pshape{1, 4, 4, 4}; + const PartialShape filters_pshape{4, 4, 3, 3}; - FAIL() << "DeformableConvolution created with incorrect 'deformable group' value"; + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // data batch has invalid rank 5, should be 4 + FAIL() << "Incompatible data batch input rank not detected"; } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), "deformable values input must be evenly divisible"); + EXPECT_HAS_SUBSTRING(error.what(), "Ranks of inputs do not match. Got: data batch " + "shape {1,4,5,5,5}, offsets shape {1,4,4,4}, filters " + "shape {4,4,3,3}"); + } + catch (...) + { + FAIL() << "Rank validation check of data batch input failed for unexpected reason"; + } + + // deformable values shape provides is rank 5 + try + { + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 4, 4, 4, 4}; + const PartialShape filters_pshape{4, 4, 3, 3}; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // deformable values has invalid rank 5, should be 4 + FAIL() << "Incompatible offsets input rank not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Ranks of inputs do not match. Got: data batch shape " + "{1,4,5,5}, offsets shape {1,4,4,4,4}, filters shape " + "{4,4,3,3}"); + } + catch (...) + { + FAIL() << "Rank validation check of offsets input failed for unexpected reason"; + } + + // filter partial shape provided is rank 5 + try + { + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 4, 4, 4}; + const PartialShape filters_pshape{4, 4, 3, 3, 3}; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // filters has invalid rank 5, should be 4 + FAIL() << "Incompatible filter input rank not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Ranks of inputs do not match. Got: data batch shape " + "{1,4,5,5}, offsets shape {1,4,4,4}, filters shape " + "{4,4,3,3,3}"); + } + catch (...) + { + FAIL() << "Rank validation check of filter input failed for unexpected reason"; + } + + // 3D deformable convolution (not supported) + try + { + const PartialShape data_batch_pshape{1, 4, 5, 5, 5}; + const PartialShape offsets_pshape{1, 4, 4, 4, 4}; + const PartialShape filters_pshape{4, 4, 3, 3, 3}; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // inputs have rank 5, should be 4 + FAIL() << "Incompatible input ranks not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Inputs must be of rank 4"); + } + catch (...) + { + FAIL() << "Rank validation check for 2 spatial dimension inputs failed for unexpected reason"; + } + + // 1D deformable convolution (not supported) + try + { + const PartialShape data_batch_pshape{1, 4, 5}; + const PartialShape offsets_pshape{1, 4, 4}; + const PartialShape filters_pshape{4, 4, 3}; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + Strides{}, + CoordinateDiff{}, + CoordinateDiff{}, + Strides{}); + // inputs have rank 3, should be 4 + FAIL() << "Incompatible input ranks not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Inputs must be of rank 4"); + } + catch (...) + { + FAIL() << "Rank validation check for 2 spatial dimension inputs failed for unexpected reason"; + } +} + +TEST(type_prop, deformable_convolution_invalid_groups) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 4, 3, 3}; + const PartialShape filters_pshape{4, 4, 3, 3}; + element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::SAME_LOWER; + const int64_t group = 0; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + + try + { + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // attribute group is invalid + FAIL() << "Invalid attribute group value not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Attribute 'group' must be any value starting from 1"); + } + catch (...) + { + FAIL() << "Attribute group validation check failed for unexpected " + "reason."; + } +} + +TEST(type_prop, deformable_convolution_invalid_deformable_groups) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 4, 3, 3}; + const PartialShape filters_pshape{4, 4, 3, 3}; + element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::SAME_LOWER; + const int64_t group = 4; + const int64_t deformable_group = 0; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + + try + { + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // attribute deformable group is invalid + FAIL() << "Invalid attribute deformable group value not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Attribute 'deformable group' must be any value starting from 1"); + } + catch (...) + { + FAIL() << "Attribute deformable group validation check failed for unexpected " + "reason."; + } +} + +TEST(type_prop, deformable_convolution_invalid_offsets_channels_dim) +{ + try + { + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 9, 3, 3}; + const PartialShape filters_pshape{4, 4, 3, 3}; + element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::SAME_LOWER; + const int64_t group = 4; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // Channels dim of deformable values is incorrect. Should be 36 + FAIL() << "Invalid channels dimension of offsets input not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "The channels dimension of offsets input is not " + "compatible with filters and 'deformable group' attribute"); + } + catch (...) + { + FAIL() << "Channels dimension of offsets input validation check failed for " + "unexpected " + "reason."; + } + + // filters spatial dims are dynamic + // we can still check if channels dim of offsets if evenly + // divisible by deformable group attribute + try + { + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 35, Dimension::dynamic(), Dimension::dynamic()}; + const PartialShape filters_pshape{4, 4, Dimension::dynamic(), Dimension::dynamic()}; + element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::SAME_LOWER; + const int64_t group = 4; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // Channels dim of deformable values is incorrect + FAIL() << "Invalid channels dimension of offsets input not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "The channels dimension of offsets input must be " + "evenly divisible by the 'deformable group' value along the " + "channels axis."); + } + catch (...) + { + FAIL() << "Channels dimension of offsets input validation check failed for " + "unexpected reason."; + } +} + +TEST(type_prop, deformable_convolution_invalid_offsets_batch_dim) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{2, 36, 3, 3}; + const PartialShape filters_pshape{4, 4, 3, 3}; + element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::SAME_LOWER; + const int64_t group = 4; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + + try + { + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // data batch and deformable values inputs must have the same batch dimension + FAIL() << "Invalid batch dimension of offsets input not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Data batch and offsets batch dimension must be same value"); + } + catch (...) + { + FAIL() + << "Batch dimension of offsets input validation check failed for unexpected " + "reason."; + } +} + +TEST(type_prop, deformable_convolution_invalid_data_batch_channels_dim_with_group) +{ + const PartialShape data_batch_pshape{1, 5, 5, 5}; + const PartialShape offsets_pshape{1, 36, 3, 3}; + const PartialShape filters_pshape{4, 5, 3, 3}; + element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::EXPLICIT; + const int64_t group = 4; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + + try + { + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // data batch channels is not evenly divisible by the attribute group value + FAIL() << "Invalid channels dimension of data batch input not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "The input data shape must be evenly divisible by the 'group' value " + "along the channels axis."); + } + catch (...) + { + FAIL() << "Data batch channel dimension validation check failed for unexpected " + "reason."; + } +} + +TEST(type_prop, deformable_convolution_invalid_filters_channels_dim_with_group) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 36, 3, 3}; + const PartialShape filters_pshape{5, 4, 3, 3}; + element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::EXPLICIT; + const int64_t group = 4; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + + try + { + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // filters channels output is not evenly divisible by the attribute group value + FAIL() << "Invalid channels output dimension of filters input not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING( + error.what(), + "The filters shape must be evenly divisible by the 'group' value along " + "the channels axis"); + } + catch (...) + { + FAIL() << "Filters channels output dimension validation check failed for unexpected " + "reason."; + } +} + +TEST(type_prop, deformable_convolution_incompatible_data_batch_and_filters_channels_dim) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 36, 3, 3}; + const PartialShape filters_pshape{4, 4, 3, 3}; + element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::EXPLICIT; + const int64_t group = 4; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + + try + { + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // data batch and filters should have same channels input dimension + FAIL() << "Incompatible channels dimension of data batch and filters input not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING( + error.what(), + "Data batch channel count (4) does not match filter input channel count (16)"); + } + catch (...) + { + FAIL() << "Data batch channel and filter channel dimension validation check failed for " + "unexpected " + "reason."; + } +} + +TEST(type_prop, deformable_convolution_invalid_offsets_spatial_dims) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 36, 4, 4}; + const PartialShape filters_pshape{4, 1, 3, 3}; + const element::Type_t et = element::f32; + + Strides strides{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + Strides dilations{1, 1}; + const auto auto_pad = op::PadType::SAME_LOWER; + const int64_t group = 4; + const int64_t deformable_group = 2; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + + try + { + auto deformable_conv = make_shared(data_batch, + offsets, + filters, + strides, + pads_begin, + pads_end, + dilations, + auto_pad, + group, + deformable_group); + // deformable values has incorrect spatial dimensions + FAIL() << "Invalid spatial dimensions of offsets not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Spatial dimensions of offsets and output must be equal"); + } + catch (...) + { + FAIL() << "Spatial dimension of offsets validation check failed for unexpected reason"; + } +} + +TEST(type_prop, deformable_convolution_invalid_conv_param_spatial_dims) +{ + const PartialShape data_batch_pshape{1, 4, 5, 5}; + const PartialShape offsets_pshape{1, 18, 3, 3}; + const PartialShape filters_pshape{4, 4, 3, 3}; + element::Type_t et = element::f32; + + // invalid strides spatial dimensions + try + { + Strides strides{1, 1, 1}; + Strides dilations{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, PartialShape::dynamic()); + auto deformable_conv = make_shared( + data_batch, offsets, filters, strides, pads_begin, pads_end, dilations); + FAIL() << "Invalid strides spatial dimensions not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Strides should be defined for all and only spatial features."); + } + catch (...) + { + FAIL() << "Strides spatial dimensions validation check failed for unexpected reason"; + } + try + { + Strides strides{1}; + Strides dilations{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + + auto data_batch = make_shared(et, PartialShape::dynamic()); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared( + data_batch, offsets, filters, strides, pads_begin, pads_end, dilations); + FAIL() << "Invalid strides spatial dimensions not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Strides should be defined for all and only spatial features."); + } + catch (...) + { + FAIL() << "Strides spatial dimensions validation check failed for unexpected reason"; + } + + // invalid dilations spatial dimensions + try + { + Strides strides{1, 1}; + Strides dilations{1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, PartialShape::dynamic()); + auto deformable_conv = make_shared( + data_batch, offsets, filters, strides, pads_begin, pads_end, dilations); + FAIL() << "Invalid dilations spatial dimensions not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Dilations should be defined for all and only spatial features."); + } + catch (...) + { + FAIL() << "Dilations spatial dimensions validation check failed for unexpected reason"; + } + try + { + Strides strides{1, 1}; + Strides dilations{1, 1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0, 0}; + + auto data_batch = make_shared(et, PartialShape::dynamic()); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared( + data_batch, offsets, filters, strides, pads_begin, pads_end, dilations); + FAIL() << "Invalid dilations spatial dimensions not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Dilations should be defined for all and only spatial features."); + } + catch (...) + { + FAIL() << "Dilations spatial dimensions validation check failed for unexpected reason"; + } + + // invalid padding spatial dimensions + try + { + Strides strides{1, 1}; + Strides dilations{1, 1}; + CoordinateDiff pads_begin{0, 0, 0}; + CoordinateDiff pads_end{0, 0}; + + auto data_batch = make_shared(et, data_batch_pshape); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, PartialShape::dynamic()); + auto deformable_conv = make_shared( + data_batch, offsets, filters, strides, pads_begin, pads_end, dilations); + FAIL() << "Invalid padding spatial dimensions not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Pads should be defined for all and only spatial features."); + } + catch (...) + { + FAIL() << "Padding spatial dimensions validation check failed for unexpected reason"; + } + try + { + Strides strides{1, 1}; + Strides dilations{1, 1}; + CoordinateDiff pads_begin{0, 0}; + CoordinateDiff pads_end{0}; + + auto data_batch = make_shared(et, PartialShape::dynamic()); + auto offsets = make_shared(et, offsets_pshape); + auto filters = make_shared(et, filters_pshape); + auto deformable_conv = make_shared( + data_batch, offsets, filters, strides, pads_begin, pads_end, dilations); + FAIL() << "Invalid padding spatial dimensions not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Pads should be defined for all and only spatial features."); + } + catch (...) + { + FAIL() << "Padding spatial dimensions validation check failed for unexpected reason"; } } From 30fa59126cdb32c838abaee8cd0036571d7ab934 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 12 May 2021 09:40:06 +0300 Subject: [PATCH 18/99] Hide some legacy symbols from IE (#5566) --- inference-engine/src/inference_engine/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/inference-engine/src/inference_engine/CMakeLists.txt b/inference-engine/src/inference_engine/CMakeLists.txt index 9eeab09e6a8..dfb306ad2fb 100644 --- a/inference-engine/src/inference_engine/CMakeLists.txt +++ b/inference-engine/src/inference_engine/CMakeLists.txt @@ -32,6 +32,9 @@ set(LEGACY_LIBRARY_SHARED_SRCS "${LEGACY_SRC_ROOT}/ngraph_ops/nms_ie.cpp" "${LEGACY_SRC_ROOT}/ngraph_ops/onehot_ie.cpp") +set_source_files_properties(${LEGACY_LIBRARY_SHARED_SRCS} PROPERTIES + COMPILE_DEFINITIONS "USE_STATIC_IE") + set(IE_STATIC_DEPENDENT_FILES ${CMAKE_CURRENT_SOURCE_DIR}/file_utils.cpp) list(REMOVE_ITEM LIBRARY_SRC ${IE_STATIC_DEPENDENT_FILES}) From 87a94e1a497400d1c15f6f1e569420efd5ffa147 Mon Sep 17 00:00:00 2001 From: Alexandra Sidorova Date: Wed, 12 May 2021 09:57:52 +0300 Subject: [PATCH 19/99] [CPU][IE TESTS] Fixed Mish (#5462) --- .../include/shared_test_classes/base/layer_test_utils.hpp | 3 ++- inference-engine/thirdparty/mkl-dnn | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/layer_test_utils.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/layer_test_utils.hpp index c6d050de904..3a75ac03c31 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/layer_test_utils.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/layer_test_utils.hpp @@ -93,7 +93,8 @@ public: const auto max = std::max(CommonTestUtils::ie_abs(res), CommonTestUtils::ie_abs(ref)); float diff = static_cast(absoluteDifference) / static_cast(max); - if (max == 0 || (diff > static_cast(threshold))) { + if (max == 0 || (diff > static_cast(threshold)) || + std::isnan(static_cast(res)) || std::isnan(static_cast(ref))) { IE_THROW() << "Relative comparison of values expected: " << ref << " and actual: " << res << " at index " << i << " with threshold " << threshold << " failed"; diff --git a/inference-engine/thirdparty/mkl-dnn b/inference-engine/thirdparty/mkl-dnn index 2dd78726213..d8514fcf88e 160000 --- a/inference-engine/thirdparty/mkl-dnn +++ b/inference-engine/thirdparty/mkl-dnn @@ -1 +1 @@ -Subproject commit 2dd787262134c20f91f222bfa776225d2dddbc9a +Subproject commit d8514fcf88e9770f671074ffe0ea853d734ebbcd From 4c452b8bb6d8c84a97fe7d30420cf9bad4e7345b Mon Sep 17 00:00:00 2001 From: Chenhu Wang Date: Wed, 12 May 2021 15:24:07 +0800 Subject: [PATCH 20/99] [CPU] MVN optimization for 1D and 2D input (#5414) --- .../mkldnn_plugin/nodes/mkldnn_mvn_node.cpp | 57 ++++++++++++------- .../src/mkldnn_plugin/nodes/mkldnn_mvn_node.h | 4 +- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.cpp index edbd4e426b1..36d9942b099 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.cpp @@ -506,7 +506,7 @@ private: Xbyak::Reg64 reg_d_bias = rdx; Xbyak::Reg64 reg_load_table = r15; - Xbyak::Reg64 reg_load_store_mask = rcx; + Xbyak::Reg64 reg_load_store_mask = rbp; Vmm vmm_val = Vmm(1); Vmm vmm_mean = Vmm(0); @@ -672,6 +672,7 @@ MKLDNNMVNNode::MKLDNNMVNNode(const std::shared_ptr& op, const mkld IE_THROW(NotImplemented) << errorMessage; } + const ngraph::Shape& inDataShape = op->input_value(0).get_shape(); if (auto mvnOp = ngraph::as_type_ptr(op)) { normalizeVariance_ = mvnOp->get_normalize_variance(); epsValue_ = mvnOp->get_eps(); @@ -681,7 +682,7 @@ MKLDNNMVNNode::MKLDNNMVNNode(const std::shared_ptr& op, const mkld } acrossChannels_ = false; - const auto& inDataShapeSize = op->input_value(0).get_shape().size(); + const auto& inDataShapeSize = inDataShape.size(); if (inDataShapeSize == mvnOp->input_value(1).get_shape()[0] + 1 || inDataShapeSize == 1) acrossChannels_ = true; } else if (auto mvnOp = ngraph::as_type_ptr(op)) { @@ -690,6 +691,37 @@ MKLDNNMVNNode::MKLDNNMVNNode(const std::shared_ptr& op, const mkld epsMode_ = INSIDE_SQRT; acrossChannels_ = mvnOp->get_across_channels(); } + + transformTo5DCase(inDataShape); +} + +void MKLDNNMVNNode::transformTo5DCase(const ngraph::Shape& shape) { + switch (shape.size()) { + // for 1 and 2 rank, if acrossChannels_ is true, adjust shape to fully vectorize under unified 5d procedure. + // otherwise there are not enough data in spatial dimension to process in one kernel. + case 1 : // C + if (acrossChannels_) { + shape5D = std::make_tuple(1, 1, 1, 1, shape[0]); + acrossChannels_ = false; + break; + } else { + shape5D = std::make_tuple(1, shape[0], 1, 1, 1); + break; + } + case 2 : // NC + if (acrossChannels_) { + shape5D = std::make_tuple(1, shape[0], 1, shape[1], 1); + acrossChannels_ = false; + break; + } else { + shape5D = std::make_tuple(shape[0], shape[1], 1, 1, 1); + break; + } + case 3 : { shape5D = std::make_tuple(shape[0], shape[1], 1, shape[2], 1); break; } + case 4 : { shape5D = std::make_tuple(shape[0], shape[1], 1, shape[2], shape[3]); break; } + case 5 : { shape5D = std::make_tuple(shape[0], shape[1], shape[2], shape[3], shape[4]); break; } + default : { IE_THROW() << "MVN layer with name '" << getName() << "' doesn't support planar layout with rank: " << shape.size(); } + } } void MKLDNNMVNNode::getSupportedDescriptors() { @@ -798,19 +830,6 @@ void MKLDNNMVNNode::initSupportedPrimitiveDescriptors() { pushDesc(MKLDNNMemory::GetPlainFormat(getChildEdgeAt(0)->getDims()), impl_type); } -std::tuple MKLDNNMVNNode::get5dShapes(const SizeVector& dims) { - std::tuple shapes; - switch (dims.size()) { - case 1 : { shapes = std::make_tuple(1, dims[0], 1, 1, 1); break; } - case 2 : { shapes = std::make_tuple(dims[0], dims[1], 1, 1, 1); break; } - case 3 : { shapes = std::make_tuple(dims[0], dims[1], 1, dims[2], 1); break; } - case 4 : { shapes = std::make_tuple(dims[0], dims[1], 1, dims[2], dims[3]); break; } - case 5 : { shapes = std::make_tuple(dims[0], dims[1], dims[2], dims[3], dims[4]); break; } - default : { IE_THROW() << "MVN layer with name '" << getName() << "' doesn't support planar layout with rank: " << dims.size(); } - } - return shapes; -} - void MKLDNNMVNNode::createPrimitive() { auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); auto& srcMemPtr = getParentEdgeAt(0)->getMemoryPtr(); @@ -832,7 +851,7 @@ void MKLDNNMVNNode::createPrimitive() { jcp.across_channels = acrossChannels_; SizeVector in_dims = getParentEdgeAt(0)->getDims().ToSizeVector(); int N = 0; - std::tie(N, jcp.C, jcp.D, jcp.H, jcp.W) = get5dShapes(in_dims); + std::tie(N, jcp.C, jcp.D, jcp.H, jcp.W) = shape5D; if (mayiuse(cpu::x64::avx512_common)) { mvn_kernel.reset(new jit_uni_mvn_kernel_f32(jcp, *attr.get())); @@ -926,7 +945,7 @@ void MKLDNNMVNNode::mvn_pln(const uint8_t* src_data, uint8_t* dst_data, const Si } size_t N = 0; size_t C = 0; size_t D = 0; size_t H = 0; size_t W = 0; - std::tie(N, C, D, H, W) = get5dShapes(dims); + std::tie(N, C, D, H, W) = shape5D; size_t C1 = H * W; size_t C2 = C1 * D; @@ -1054,7 +1073,7 @@ void MKLDNNMVNNode::mvn_ref(const uint8_t* src_data, uint8_t* dst_data, const Si const float *src_data_ptr = reinterpret_cast(src_data); float *dst_data_ptr = reinterpret_cast(dst_data); size_t N = 0; size_t C = 0; size_t D = 0; size_t H = 0; size_t W = 0; - std::tie(N, C, D, H, W) = get5dShapes(dims); + std::tie(N, C, D, H, W) = shape5D; size_t C1 = H * W; size_t C2 = C1 * D; @@ -1157,7 +1176,7 @@ void MKLDNNMVNNode::mvn_blk(const uint8_t* src_data, uint8_t* dst_data, const Si } size_t N = 1; size_t C = 1; size_t D = 1; size_t H = 1; size_t W = 1; - std::tie(N, C, D, H, W) = get5dShapes(dims); + std::tie(N, C, D, H, W) = shape5D; bool is_nhwc = false; Layout layout = getParentEdgeAt(0)->getDesc().getLayout(); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h index af282cc3d8a..d988c1d103c 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h @@ -103,7 +103,9 @@ private: void setPostOps(mkldnn::primitive_attr &attr, bool initWeights = false); - std::tuple get5dShapes(const InferenceEngine::SizeVector& dims); + void transformTo5DCase(const ngraph::Shape& shape); + + std::tuple shape5D; bool acrossChannels_ = false; bool normalizeVariance_ = true; From cfc235bd653616020aed1234f935ee09943c01ac Mon Sep 17 00:00:00 2001 From: Egor Duplensky Date: Wed, 12 May 2021 11:21:05 +0300 Subject: [PATCH 21/99] [CPU] Do not set BF16 on input port for Eltwise after Input (#5542) * [CPU] Do not set BF16 on input port for Eltwise after Input Since Eltwise supports conversion to BF16 Thus unnecessary Reorder is avoided * Create a separate function for enforcing BF16 on ports * Add test to verify that no extra Reorder is inserted Also: - update legacy test - remove extra code which is not applicable anymore * Correct expected precision in legacy test --- .../src/mkldnn_plugin/mkldnn_graph.cpp | 58 +++++++++-------- .../src/mkldnn_plugin/mkldnn_graph.h | 1 + .../mkldnn_plugin/mkldnn_graph_optimizer.cpp | 7 --- .../gather_x2_add_mul_relu_concat_matmul.cpp | 2 +- .../src/input_noreorder_eltwise_bf16.cpp | 62 +++++++++++++++++++ 5 files changed, 95 insertions(+), 35 deletions(-) create mode 100644 inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/input_noreorder_eltwise_bf16.cpp diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp index a80c788f5ec..1caedcaba75 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp @@ -262,33 +262,8 @@ void MKLDNNGraph::Replicate(const CNNNetwork &network, const MKLDNNExtensionMana graphNodes.push_back(outNode); } - // We set all non const data paths precision to BF16 in case enforceBF16 flag is switched on. - if (config.enforceBF16) { - bool isQuantizedModel = false; - for (auto& node : graphNodes) { - if (node->getType() == FakeQuantize) - isQuantizedModel = true; - } - - // Floating point parts of FP32 + INT8 or FP32 + BIN mixed precision models will be executed in BF16 precision - // only if enforceBF16 flag was set manually because current performance is not good enough to enable it by default - if (implication(isQuantizedModel, config.manualEnforceBF16)) { - for (auto &node : graphNodes) { - if (node->getType() != Input && node->getType() != Output) { - for (size_t i = 0; i < node->getOriginalInputsNumber(); i++) { - auto &parent = node->getParentEdgesAtPort(i)[0]->getParent(); - if (!(parent->getType() == Input && parent->isConstant()) && node->getOriginalInputPrecisionAtPort(i) == Precision::FP32) - node->setOriginalInputPrecisionAtPort(i, Precision::BF16); - } - - for (size_t i = 0; i < node->getOriginalOutputsNumber(); i++) { - if (node->getOriginalOutputPrecisionAtPort(i) == Precision::FP32) - node->setOriginalOutputPrecisionAtPort(i, Precision::BF16); - } - } - } - } - } + if (config.enforceBF16) + EnforceBF16(); // change precision for input/output nodes to avoid extra data conversion when set input/output blobs // also we need to change input/output precisions for consumers/producers to avoid inserting reorder @@ -1201,6 +1176,35 @@ bool MKLDNNGraph::InsertNode(MKLDNNNodePtr parent, MKLDNNNodePtr child, MKLDNNNo return true; } +// Set all non const data paths precision to BF16 +void MKLDNNGraph::EnforceBF16() { + bool isQuantizedModel = false; + for (auto& node : graphNodes) { + if (node->getType() == FakeQuantize) + isQuantizedModel = true; + } + + // Floating point parts of FP32 + INT8 or FP32 + BIN mixed precision models will be executed in BF16 precision + // only if enforceBF16 flag was set manually because current performance is not good enough to enable it by default + if (implication(isQuantizedModel, config.manualEnforceBF16)) { + for (auto &node : graphNodes) { + if (node->getType() != Input && node->getType() != Output) { + for (size_t i = 0; i < node->getOriginalInputsNumber(); i++) { + auto &parent = node->getParentEdgesAtPort(i)[0]->getParent(); + if (!(parent->getType() == Input && parent->isConstant()) && // exclude nodes after Constant Inputs + !(parent->getType() == Input && node->getType() == Eltwise) && // exclude Eltwise after Input since it supports conversion to BF16 + node->getOriginalInputPrecisionAtPort(i) == Precision::FP32) + node->setOriginalInputPrecisionAtPort(i, Precision::BF16); + } + + for (size_t i = 0; i < node->getOriginalOutputsNumber(); i++) { + if (node->getOriginalOutputPrecisionAtPort(i) == Precision::FP32) + node->setOriginalOutputPrecisionAtPort(i, Precision::BF16); + } + } + } + } +} InferenceEngine::CNNNetwork MKLDNNGraph::dump() const { return dump_graph_as_ie_ngraph_net(*this); diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph.h b/inference-engine/src/mkldnn_plugin/mkldnn_graph.h index 4a82f9c26b0..29c07120fbf 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph.h @@ -204,6 +204,7 @@ protected: friend InferenceEngine::CNNNetwork dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph); private: + void EnforceBF16(); void printGraphInfo() const; }; diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp index d5f2e3819be..f773507b657 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp @@ -142,13 +142,6 @@ void MKLDNNGraphOptimizer::ApplyImplSpecificGraphOptimizations(MKLDNNGraph &grap DropDoubleReorders(graph); graph.RemoveDroppedNodes(); -#if 0 - /* disable, since there is no use case for it at the moment - * should be enabled after ngraph migration */ - DropConvertReorder(graph); - graph.RemoveDroppedNodes(); -#endif - MergeTransposeAndReorder(graph); graph.RemoveDroppedNodes(); diff --git a/inference-engine/tests/functional/plugin/cpu/bfloat16/gather_x2_add_mul_relu_concat_matmul.cpp b/inference-engine/tests/functional/plugin/cpu/bfloat16/gather_x2_add_mul_relu_concat_matmul.cpp index 74b50d158d7..492faef5314 100644 --- a/inference-engine/tests/functional/plugin/cpu/bfloat16/gather_x2_add_mul_relu_concat_matmul.cpp +++ b/inference-engine/tests/functional/plugin/cpu/bfloat16/gather_x2_add_mul_relu_concat_matmul.cpp @@ -123,7 +123,7 @@ protected: // performance counters expectedPrecisions["Matmul_0"] = "BF16"; expectedPrecisions["Mul_1"] = "BF16"; - expectedPrecisions["Add_1"] = "BF16"; + expectedPrecisions["Add_1"] = netPrecision.name(); // FP32->BF16 in case of FP32 net, BF16->BF16 in case of BF16 net expectedPrecisions["Relu_1"] = "ndef"; expectedPrecisions["Conc_1"] = "BF16"; expectedPrecisions["Matmul_1"] = "BF16"; diff --git a/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/input_noreorder_eltwise_bf16.cpp b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/input_noreorder_eltwise_bf16.cpp new file mode 100644 index 00000000000..f09724a596a --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/input_noreorder_eltwise_bf16.cpp @@ -0,0 +1,62 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "ie_common.h" +#include "ngraph_functions/utils/ngraph_helpers.hpp" +#include "test_utils/cpu_test_utils.hpp" + +using namespace InferenceEngine; +using namespace CPUTestUtils; + +namespace CPULayerTestsDefinitions { + +class InputNoReorderEltwiseBF16 : virtual public LayerTestsUtils::LayerTestsCommon, + public CPUTestsBase { +protected: + void SetUp() { + auto netPrecision = inPrc = Precision::FP32; + outPrc = Precision::BF16; + targetDevice = CommonTestUtils::DEVICE_CPU; + std::map additional_config{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}; + configuration.insert(additional_config.begin(), additional_config.end()); + + std::vector inputShape {2, 4, 4, 1}; + std::vector outputShape = inputShape; + auto eltwiseType = ngraph::helpers::EltwiseTypes::ADD; + auto secondaryInputType = ngraph::helpers::InputLayerType::CONSTANT; + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto input = ngraph::builder::makeParams(ngPrc, {inputShape}); + std::shared_ptr secondaryInput = ngraph::builder::makeInputLayer(ngPrc, secondaryInputType, inputShape); + auto eltwise = ngraph::builder::makeEltwise(input[0], secondaryInput, eltwiseType); + + function = makeNgraphFunction(ngPrc, input, eltwise, "Eltwise"); + } +}; + +/* FP32 network with enforced BF16 precision. + * Test that no Reorder (or Convert) is inserted after Input. + * Eltwise performs the conversion by itself. + + Input[FP32] Constant[FP32] + \ / + \ / + X No Reorder X + \ / + Eltwise[FP32->BF16] + | + | + Output[BF16] +*/ +TEST_F(InputNoReorderEltwiseBF16, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + Run(); + + CheckNodeOfTypeCount(executableNetwork, "Reorder", 0); + CheckNodeOfTypeCount(executableNetwork, "Convert", 0); + CheckNodeOfTypeCount(executableNetwork, "Eltwise", 1); +} +} // namespace CPULayerTestsDefinitions From 932467631e9fcbf59a6108af11433fcc32da856a Mon Sep 17 00:00:00 2001 From: Bartosz Sledz Date: Wed, 12 May 2021 10:27:02 +0200 Subject: [PATCH 22/99] Change broadcasted shape for mul, add and sub (dequantization) (#4865) * Change broadcast target shape for mul, add and sub transformation * Revert "Change broadcast target shape for mul, add and sub transformation" This reverts commit cb1332ffc4454c8a39c12fbb78b995bd64fa8db1. * Address comments * Adjust functests * Adjust next functests * Revert "Adjust next functests" This reverts commit 529b314b709023972b9c2c08c9bc788bb3bc9a37. * Revert "Address comments" This reverts commit 9fccfc32b1f715f3a559ca3730a26c33b4f1be51. * Revert "Adjust functests" This reverts commit ef5fea700616dc1286bbca620cff614efd76ffaa. * Implement new approach * Address comment * Add functests --- .../convert_mul_or_add_finally.cpp | 7 +- .../mul_add_conversion_test.cpp | 116 ++++++++++-------- 2 files changed, 74 insertions(+), 49 deletions(-) diff --git a/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_or_add_finally.cpp b/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_or_add_finally.cpp index 150e60cda34..0ad0b349996 100644 --- a/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_or_add_finally.cpp +++ b/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_or_add_finally.cpp @@ -140,6 +140,12 @@ ngraph::matcher_pass_callback get_callback() { } const ngraph::Shape constShape = constant->get_output_shape(0); + const ngraph::Shape shape = partialShape.to_shape(); + + if (constShape.size() == 1ul && constShape[0] != 1 && constShape[0] != shape[1]) { + return false; + } + if ((constShape.size() > 5ul)) { return false; } @@ -148,7 +154,6 @@ ngraph::matcher_pass_callback get_callback() { return true; } - const ngraph::Shape shape = partialShape.to_shape(); if (constShape.size() == shape.size()) { if ((constShape[0] != 1ul) || (constShape[1] != shape[1])) { return false; diff --git a/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp index 3e2cb156b5d..22c18407a07 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp @@ -26,6 +26,7 @@ #include #include "common_test_utils/ngraph_test_utils.hpp" +#include "lpt_ngraph_functions/common/builders.hpp" using namespace testing; @@ -40,10 +41,11 @@ struct ConstantParams { }; using MulConstant = ConstantParams; using AddConstant = ConstantParams; -using RefFunction = std::function(const InputShape&, const MulConstant&, const AddConstant&)>; +using IsDequantization = bool; +using RefFunction = std::function(const InputShape&, const MulConstant&, const AddConstant&, const IsDequantization&)>; class MulAddConversionTests: public CommonTestUtils::TestsCommon, -public testing::WithParamInterface, RefFunction> > { +public testing::WithParamInterface, RefFunction> > { public: std::shared_ptr f, f_ref; @@ -52,23 +54,31 @@ public: const auto& input_shape = std::get<0>(attrs); const auto& mul_const = std::get<1>(attrs); const auto& add_const = std::get<2>(attrs); + const auto& is_dequantization = std::get<3>(attrs); const auto& get_ref_function = std::get<1>(GetParam()); - f = get_initial_function(input_shape, mul_const, add_const); - f_ref = get_ref_function(input_shape, mul_const, add_const); + f = get_initial_function(input_shape, mul_const, add_const, is_dequantization); + f_ref = get_ref_function(input_shape, mul_const, add_const, is_dequantization); } static std::shared_ptr get_initial_function(const InputShape& input_shape, const MulConstant& mul_const, - const AddConstant& add_const) { + const AddConstant& add_const, + const IsDequantization& is_dequantization) { auto input = std::make_shared(ngraph::element::f32, input_shape); ngraph::Output last = input; if (!mul_const.skip) { last = std::make_shared(last, create_constant(mul_const.shape, mul_const.value)); + if (is_dequantization) { + ngraph::builder::subgraph::addDequantizationAttribute(last.get_node_shared_ptr()); + } } if (!add_const.skip) { last = std::make_shared(last, create_constant(add_const.shape, add_const.value)); + if (is_dequantization) { + ngraph::builder::subgraph::addDequantizationAttribute(last.get_node_shared_ptr()); + } } last = std::make_shared(last); return std::make_shared(ngraph::NodeVector{last.get_node_shared_ptr()}, ngraph::ParameterVector{input}); @@ -77,7 +87,8 @@ public: static std::shared_ptr get_scale_shift_reference(const InputShape& input_shape, const MulConstant& mul_const, - const AddConstant& add_const) { + const AddConstant& add_const, + const IsDequantization& is_dequanization) { if (mul_const.skip && add_const.skip) { throw ngraph::ngraph_error("Invalid arguments"); } @@ -94,7 +105,8 @@ public: static std::shared_ptr get_power_reference(const InputShape& input_shape, const MulConstant& mul_const, - const AddConstant& add_const) { + const AddConstant& add_const, + const IsDequantization& is_dequanization) { auto input = std::make_shared(ngraph::element::f32, input_shape); float scale(1), shift(0); if (!mul_const.skip) scale = mul_const.value; @@ -107,7 +119,8 @@ public: static std::shared_ptr get_eltwise_add_reference(const InputShape& input_shape, const MulConstant& mul_const, - const AddConstant& add_const) { + const AddConstant& add_const, + const IsDequantization& is_dequanization) { auto input = std::make_shared(ngraph::element::f32, input_shape); auto add = std::make_shared(input, create_constant(add_const.shape, add_const.value), ELTWISE_TYPE::Sum); auto relu = std::make_shared(add); @@ -117,7 +130,8 @@ public: static std::shared_ptr get_eltwise_mul_reference(const InputShape& input_shape, const MulConstant& mul_const, - const AddConstant& add_const) { + const AddConstant& add_const, + const IsDequantization& is_dequanization) { auto input = std::make_shared(ngraph::element::f32, input_shape); auto mul = std::make_shared(input, create_constant(mul_const.shape, mul_const.value), ELTWISE_TYPE::Prod); auto relu = std::make_shared(mul); @@ -165,146 +179,152 @@ TEST_P(MulOrAddConversionTests, CompareFunctions) { INSTANTIATE_TEST_CASE_P(MulAddToScaleShift, MulAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, 64, 64}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5)), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, 64}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5)), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, DYN}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5))), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false)), testing::Values(SCALESHIFT))); INSTANTIATE_TEST_CASE_P(MulToScaleShift, MulOrAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, 64, 64}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{DYN, 3, DYN, 64}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{DYN, 3, DYN, DYN}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - NONE)), + NONE, false)), testing::Values(SCALESHIFT))); INSTANTIATE_TEST_CASE_P(AddToScaleShift, MulOrAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, 64, 64}, NONE, - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5)), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, 64}, NONE, - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5)), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, DYN}, NONE, - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5))), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false)), testing::Values(SCALESHIFT))); INSTANTIATE_TEST_CASE_P(MulAddToPower, MulAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, 64, 64}, CONST(ngraph::Shape({1}), 0.5), - CONST(ngraph::Shape({1}), 0.5)), + CONST(ngraph::Shape({1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, 64}, CONST(ngraph::Shape({1}), 0.5), - CONST(ngraph::Shape({1}), 0.5)), + CONST(ngraph::Shape({1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, DYN}, CONST(ngraph::Shape({1}), 0.5), - CONST(ngraph::Shape({1}), 0.5))), + CONST(ngraph::Shape({1}), 0.5), false)), testing::Values(POWER))); INSTANTIATE_TEST_CASE_P(MulToPower, MulOrAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, 64, 64}, CONST(ngraph::Shape({1}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{DYN, 3, DYN, 64}, CONST(ngraph::Shape({1}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{DYN, 3, DYN, DYN}, CONST(ngraph::Shape({1}), 0.5), - NONE)), + NONE, false)), testing::Values(POWER))); INSTANTIATE_TEST_CASE_P(AddToPower, MulOrAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, 64, 64}, NONE, - CONST(ngraph::Shape({1}), 0.5)), + CONST(ngraph::Shape({1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, 64}, NONE, - CONST(ngraph::Shape({1}), 0.5)), + CONST(ngraph::Shape({1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, DYN}, NONE, - CONST(ngraph::Shape({1}), 0.5))), + CONST(ngraph::Shape({1}), 0.5), false)), testing::Values(POWER))); INSTANTIATE_TEST_CASE_P(MulAddNegative, MulAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, DYN}, CONST(ngraph::Shape({1, 1, 3, 1}), 0.5), - CONST(ngraph::Shape({3, 1}), 0.5)/*detect broadcast case*/), + CONST(ngraph::Shape({3, 1}), 0.5)/*detect broadcast case*/, false), std::make_tuple(InputShape{DYN, 3, DYN}, CONST(ngraph::Shape({3, 1}), 0.5), - CONST(ngraph::Shape({1, 1, 3, 1}), 0.5)/*detect broadcast case*/), + CONST(ngraph::Shape({1, 1, 3, 1}), 0.5)/*detect broadcast case*/, false), std::make_tuple(InputShape{DYN, DYN, DYN, DYN}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5)), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false), std::make_tuple(InputShape{DYN, DYN, DYN, DYN}, CONST(ngraph::Shape({1, 3, 2, 1}), 0.5), - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5)), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false), std::make_tuple(InputShape{1, 3, 2}, CONST(ngraph::Shape({1, 3, 1}), 0.5), - CONST(ngraph::Shape({1, 3, 2}), 0.5)), + CONST(ngraph::Shape({1, 3, 2}), 0.5), false), std::make_tuple(InputShape{1, DYN, 64, 64}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5))), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false)), testing::Values(SAME))); INSTANTIATE_TEST_CASE_P(MulToEltwise, MulOrAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, 64}, CONST(ngraph::Shape({1, 1, 64}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{DYN, 3, DYN}, CONST(ngraph::Shape({1, 1, 3, 1}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{DYN, DYN, DYN, DYN}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{DYN, 3, DYN, DYN}, CONST(ngraph::Shape({1, 3, 2, 1}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{1, 3, 2}, CONST(ngraph::Shape({1, 3, 2}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{1, DYN, 64, 64}, CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), - NONE), + NONE, false), std::make_tuple(InputShape{64, 1, 64}, CONST(ngraph::Shape({64, 64, 64}), 1), - NONE), + NONE, false), std::make_tuple(InputShape{64, 64, 1}, CONST(ngraph::Shape({1, 1, 64}), 1), - NONE), + NONE, false), std::make_tuple(InputShape{DYN, 1, 64}, CONST(ngraph::Shape({64, 1, 64}), 1), - NONE)), + NONE, false), + std::make_tuple(InputShape{1, 1024, 768}, + CONST(ngraph::Shape({768}), 0.5), + NONE, true)), testing::Values(ELTWISE_PROD))); INSTANTIATE_TEST_CASE_P(AddToEltwise, MulOrAddConversionTests, testing::Combine( testing::Values(std::make_tuple(InputShape{DYN, 3, 64}, NONE, - CONST(ngraph::Shape({1, 1, 64}), 0.5)), + CONST(ngraph::Shape({1, 1, 64}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN}, NONE, - CONST(ngraph::Shape({1, 1, 3, 1}), 0.5)), + CONST(ngraph::Shape({1, 1, 3, 1}), 0.5), false), std::make_tuple(InputShape{DYN, DYN, DYN, DYN}, NONE, - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5)), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false), std::make_tuple(InputShape{DYN, 3, DYN, DYN}, NONE, - CONST(ngraph::Shape({1, 3, 2, 1}), 0.5)), + CONST(ngraph::Shape({1, 3, 2, 1}), 0.5), false), std::make_tuple(InputShape{1, 3, 2}, NONE, - CONST(ngraph::Shape({1, 3, 2}), 0.5)), + CONST(ngraph::Shape({1, 3, 2}), 0.5), false), std::make_tuple(InputShape{1, DYN, 64, 64}, NONE, - CONST(ngraph::Shape({1, 3, 1, 1}), 0.5))), + CONST(ngraph::Shape({1, 3, 1, 1}), 0.5), false), + std::make_tuple(InputShape{1, 1024, 768}, + NONE, + CONST(ngraph::Shape({768}), 0.5), true)), testing::Values(ELTWISE_SUM))); #undef CONST From 81f9d78541e5e4986bc612724e0b96eb0173540b Mon Sep 17 00:00:00 2001 From: Bartosz Sledz Date: Wed, 12 May 2021 10:32:34 +0200 Subject: [PATCH 23/99] ONNX Subgraph - Infer types of inputs from top level Graph nodes (#5277) --- .../include/onnx_import/core/node.hpp | 4 + .../onnx_import/src/core/attribute.cpp | 54 +++-- .../onnx_import/src/core/attribute.hpp | 6 +- .../frontend/onnx_import/src/core/graph.cpp | 44 ++--- .../frontend/onnx_import/src/core/graph.hpp | 32 +-- .../frontend/onnx_import/src/core/model.cpp | 4 +- .../frontend/onnx_import/src/core/model.hpp | 8 +- ngraph/frontend/onnx_import/src/core/node.cpp | 37 +++- ngraph/frontend/onnx_import/src/op/loop.cpp | 10 +- .../frontend/onnx_import/src/utils/common.hpp | 12 ++ .../onnx_import/src/utils/onnx_internal.cpp | 6 +- ngraph/python/tests/test_onnx/test_backend.py | 8 +- ...ode_from_parent_scope_infer_types.prototxt | 176 +++++++++++++++++ ...x_controlflow_loop_2d_infer_types.prototxt | 184 ++++++++++++++++++ .../test/onnx/onnx_import_controlflow.in.cpp | 43 ++++ 15 files changed, 543 insertions(+), 85 deletions(-) create mode 100644 ngraph/test/models/onnx/loop/loop_add_node_from_parent_scope_infer_types.prototxt create mode 100644 ngraph/test/models/onnx/loop/onnx_controlflow_loop_2d_infer_types.prototxt diff --git a/ngraph/frontend/onnx_import/include/onnx_import/core/node.hpp b/ngraph/frontend/onnx_import/include/onnx_import/core/node.hpp index 9c4462e6728..fa39bd0fd46 100644 --- a/ngraph/frontend/onnx_import/include/onnx_import/core/node.hpp +++ b/ngraph/frontend/onnx_import/include/onnx_import/core/node.hpp @@ -74,6 +74,10 @@ namespace ngraph bool has_attribute(const std::string& name) const; + Subgraph get_subgraph_from_attribute( + const std::string& name, + const std::map& carried_dependencies_map) const; + template T get_attribute_value(const std::string& name, T default_value) const; diff --git a/ngraph/frontend/onnx_import/src/core/attribute.cpp b/ngraph/frontend/onnx_import/src/core/attribute.cpp index 950a8494fb7..8eaa8c93517 100644 --- a/ngraph/frontend/onnx_import/src/core/attribute.cpp +++ b/ngraph/frontend/onnx_import/src/core/attribute.cpp @@ -5,37 +5,57 @@ #include "core/attribute.hpp" #include "core/graph.hpp" #include "core/model.hpp" +#include "ngraph/log.hpp" namespace ngraph { namespace onnx_import { - std::vector Attribute::get_graph_array(Model& model) const - { - std::vector result; - for (const auto& graph : m_attribute_proto->graphs()) - { - result.emplace_back(graph, model); - } - return result; - } - - Subgraph Attribute::get_subgraph(const Graph& parent_graph) const + Subgraph Attribute::get_subgraph( + const Graph& parent_graph, + const std::map& carried_dependencies_map) const { if (m_attribute_proto->type() != ONNX_NAMESPACE::AttributeProto_AttributeType_GRAPH) { throw error::attribute::InvalidData{m_attribute_proto->type()}; } - ONNX_NAMESPACE::ModelProto model_proto; + auto model_proto = common::make_unique(); + const auto& graph = m_attribute_proto->g(); - *(model_proto.mutable_graph()) = graph; + model_proto->mutable_graph()->CopyFrom(graph); + + const std::size_t subgraph_inputs_count = + static_cast(model_proto->mutable_graph()->mutable_input()->size()); + // Use the `carried_dependencies_map` to infer the types for the subgraph inputs + for (const auto& carried_dependency : carried_dependencies_map) + { + if (carried_dependency.first >= subgraph_inputs_count) + { + NGRAPH_WARN << "Input with index: '" << carried_dependency.first + << "' was not found in the subgraph"; + } + else + { + const auto& parent_in = + parent_graph.get_ng_node_from_cache(carried_dependency.second); + const auto& carried_type = parent_in.get_element_type(); + auto subgraph_in = + model_proto->mutable_graph()->mutable_input(carried_dependency.first); + auto subgraph_in_tensor_type = + subgraph_in->mutable_type()->mutable_tensor_type(); + if (!subgraph_in_tensor_type->has_elem_type()) + { + subgraph_in_tensor_type->set_elem_type( + onnx_common::ng_to_onnx_data_type(carried_type)); + } + } + } // set opset version and domain from the parent graph - *model_proto.mutable_opset_import() = parent_graph.get_opset_imports(); - - Model model{model_proto}; - return Subgraph{graph, model, parent_graph}; + model_proto->mutable_opset_import()->CopyFrom(parent_graph.get_opset_imports()); + auto model = common::make_unique(std::move(model_proto)); + return Subgraph{std::move(model), parent_graph}; } } // namespace onnx_import diff --git a/ngraph/frontend/onnx_import/src/core/attribute.hpp b/ngraph/frontend/onnx_import/src/core/attribute.hpp index 4c86ba2ba11..80a287a55fb 100644 --- a/ngraph/frontend/onnx_import/src/core/attribute.hpp +++ b/ngraph/frontend/onnx_import/src/core/attribute.hpp @@ -281,7 +281,9 @@ namespace ngraph float get_float() const { return m_attribute_proto->f(); } int64_t get_integer() const { return m_attribute_proto->i(); } const std::string& get_string() const { return m_attribute_proto->s(); } - Subgraph get_subgraph(const Graph& parent_graph) const; + Subgraph get_subgraph( + const Graph& parent_graph, + const std::map& carried_dependencies_map) const; std::vector get_tensor_array() const { @@ -306,8 +308,6 @@ namespace ngraph std::end(m_attribute_proto->strings())}; } - std::vector get_graph_array(Model&) const; - /* explicit */ operator ONNX_NAMESPACE::AttributeProto_AttributeType() const { return m_attribute_proto->type(); diff --git a/ngraph/frontend/onnx_import/src/core/graph.cpp b/ngraph/frontend/onnx_import/src/core/graph.cpp index e5323b67fa2..c8f56327d6b 100644 --- a/ngraph/frontend/onnx_import/src/core/graph.cpp +++ b/ngraph/frontend/onnx_import/src/core/graph.cpp @@ -52,8 +52,8 @@ namespace ngraph } } // namespace detail - Graph::Graph(const ONNX_NAMESPACE::GraphProto& graph_proto, Model& model) - : Graph(graph_proto, model, std::unique_ptr(new GraphCache())) + Graph::Graph(std::unique_ptr&& model) + : Graph(std::move(model), common::make_unique()) { // Remove dangling Parameters for (auto param_it = m_parameters.begin(); param_it != m_parameters.end();) @@ -75,27 +75,14 @@ namespace ngraph param_it++; } } - Graph::Graph(const Graph& graph) - : m_parameters(graph.m_parameters) - , m_cache{new GraphCache(*graph.m_cache)} - , m_graph_proto{graph.m_graph_proto} - , m_nodes(graph.m_nodes) - , m_inputs(graph.m_inputs) - , m_outputs(graph.m_outputs) - , m_model{graph.m_model} - { - } - Graph::Graph(const ONNX_NAMESPACE::GraphProto& graph_proto, - Model& model, - std::unique_ptr&& cache) - : m_cache{std::move(cache)} - , m_graph_proto{&graph_proto} - , m_model{&model} + Graph::Graph(std::unique_ptr&& model, std::unique_ptr&& cache) + : m_model{std::move(model)} + , m_cache{std::move(cache)} { std::map initializers; // Process all initializers in the graph - for (const auto& initializer_tensor : m_graph_proto->initializer()) + for (const auto& initializer_tensor : m_model->get_graph().initializer()) { if (initializer_tensor.has_name()) { @@ -133,7 +120,7 @@ namespace ngraph } // Process all ONNX graph inputs, convert them to nGraph nodes and store in cache - for (const auto& input : m_graph_proto->input()) + for (const auto& input : m_model->get_graph().input()) { m_inputs.emplace_back(input); @@ -150,7 +137,7 @@ namespace ngraph } // Process all graph outputs - for (const auto& output : m_graph_proto->output()) + for (const auto& output : m_model->get_graph().output()) { m_outputs.emplace_back(output); } @@ -158,7 +145,7 @@ namespace ngraph // Verify that ONNX graph contains only nodes of available operator types std::map> unknown_operators; - for (const auto& node_proto : m_graph_proto->node()) + for (const auto& node_proto : m_model->get_graph().node()) { if (!m_model->is_operator_available(node_proto)) { @@ -189,7 +176,7 @@ namespace ngraph detail::to_string(unknown_operators)); // Process ONNX graph nodes, convert to nGraph nodes - for (const auto& node_proto : m_graph_proto->node()) + for (const auto& node_proto : m_model->get_graph().node()) { m_nodes.emplace_back(node_proto, *this); const Node& node{m_nodes.back()}; @@ -219,7 +206,7 @@ namespace ngraph OutputVector Graph::get_ng_outputs() const { OutputVector results; - for (const auto& output : m_graph_proto->output()) + for (const auto& output : m_model->get_graph().output()) { const auto& ng_output = get_ng_node_from_cache(output.name()); if (!ngraph::op::is_null(ng_output)) // ignore optional outputs @@ -335,17 +322,14 @@ namespace ngraph return m_model->get_opset_imports(); } - Subgraph::Subgraph(const ONNX_NAMESPACE::GraphProto& proto, - Model& model, - const Graph& parent_graph) + Subgraph::Subgraph(std::unique_ptr&& model, const Graph& parent_graph) : Graph( - proto, - model, + std::move(model), std::unique_ptr(new SubgraphCache(parent_graph.get_graph_cache()))) { // find all nodes on edge parent graph-subgraph // (it means input of node from parent graph, output from subgraph) - for (const auto& node_proto : proto.node()) + for (const auto& node_proto : m_model->get_graph().node()) { int input_index = 0; for (const auto& in_name : node_proto.input()) diff --git a/ngraph/frontend/onnx_import/src/core/graph.hpp b/ngraph/frontend/onnx_import/src/core/graph.hpp index 14e3e72f40c..6cbd8804109 100644 --- a/ngraph/frontend/onnx_import/src/core/graph.hpp +++ b/ngraph/frontend/onnx_import/src/core/graph.hpp @@ -23,8 +23,14 @@ namespace ngraph class Graph { public: - Graph(const ONNX_NAMESPACE::GraphProto& proto, Model& model); - Graph(const Graph& graph); + Graph(std::unique_ptr&& model); + Graph() = delete; + + Graph(const Graph&) = delete; + Graph(Graph&&) = default; + + Graph& operator=(const Graph&) = delete; + Graph& operator=(Graph&&) = default; const std::vector& get_nodes() const { return m_nodes; } const std::vector& get_inputs() const { return m_inputs; } const std::vector& get_outputs() const { return m_outputs; } @@ -32,16 +38,14 @@ namespace ngraph const ParameterVector& get_ng_parameters() const { return m_parameters; } bool is_node_in_cache(const std::string& name) const; Output get_ng_node_from_cache(const std::string& name) const; - const std::string& get_name() const { return m_graph_proto->name(); } + const std::string& get_name() const { return m_model->get_graph().name(); } OutputVector make_ng_nodes(const Node& onnx_node) const; const GraphCache& get_graph_cache() const; const OpsetImports& get_opset_imports() const; virtual ~Graph() = default; protected: - Graph(const ONNX_NAMESPACE::GraphProto& proto, - Model& model, - std::unique_ptr&& cache); + Graph(std::unique_ptr&& model, std::unique_ptr&& cache); void set_friendly_names(const Node& onnx_node, const OutputVector& ng_node_vector) const; @@ -57,14 +61,13 @@ namespace ngraph protected: ParameterVector m_parameters; + std::unique_ptr m_model; std::unique_ptr m_cache; private: - const ONNX_NAMESPACE::GraphProto* m_graph_proto; std::vector m_nodes; std::vector m_inputs; std::vector m_outputs; - Model* m_model; }; /// \brief Representation of ONNX subgraph. It is used for example by ONNX Loop op. @@ -75,17 +78,22 @@ namespace ngraph public: /// \brief Subgraph a GraphCache class object. /// - /// \param[in] proto The ONNX protobuf graph representation. /// \param[in] model The ONNX model object. /// \param[in] parent_graph The reference to the parent graph. - Subgraph(const ONNX_NAMESPACE::GraphProto& proto, - Model& model, - const Graph& parent_graph); + Subgraph(std::unique_ptr&& model, const Graph& parent_graph); /// \brief Return outputs which are on the edge the subgraph and the parent graph. /// \return Vector of edge nodes from parent scope. const std::vector> get_outputs_from_parent() const; + Subgraph() = delete; + + Subgraph(const Subgraph&) = delete; + Subgraph(Subgraph&&) = default; + + Subgraph& operator=(const Subgraph&) = delete; + Subgraph& operator=(Subgraph&&) = default; + private: std::vector> m_outputs_from_parent; }; diff --git a/ngraph/frontend/onnx_import/src/core/model.cpp b/ngraph/frontend/onnx_import/src/core/model.cpp index 0878b9c1463..452aea7b477 100644 --- a/ngraph/frontend/onnx_import/src/core/model.cpp +++ b/ngraph/frontend/onnx_import/src/core/model.cpp @@ -31,8 +31,8 @@ namespace ngraph throw ngraph_error("Couldn't find operator set's version for domain: " + domain + "."); } - Model::Model(const ONNX_NAMESPACE::ModelProto& model_proto) - : m_model_proto{&model_proto} + Model::Model(std::unique_ptr&& model_proto) + : m_model_proto{std::move(model_proto)} { // Walk through the elements of opset_import field and register operator sets // for each domain. An exception UnknownDomain() will raise if the domain is diff --git a/ngraph/frontend/onnx_import/src/core/model.hpp b/ngraph/frontend/onnx_import/src/core/model.hpp index e17d9e1689c..993dfb97e1a 100644 --- a/ngraph/frontend/onnx_import/src/core/model.hpp +++ b/ngraph/frontend/onnx_import/src/core/model.hpp @@ -28,10 +28,10 @@ namespace ngraph { public: Model() = delete; - explicit Model(const ONNX_NAMESPACE::ModelProto& model_proto); + explicit Model(std::unique_ptr&& model_proto); - Model(const Model&) = default; - Model(Model&&) = default; + Model(const Model&) = delete; + Model(Model&&) = delete; Model& operator=(const Model&) = delete; Model& operator=(Model&&) = delete; @@ -71,7 +71,7 @@ namespace ngraph void enable_opset_domain(const std::string& domain); private: - const ONNX_NAMESPACE::ModelProto* m_model_proto; + const std::unique_ptr m_model_proto; std::unordered_map m_opset; }; diff --git a/ngraph/frontend/onnx_import/src/core/node.cpp b/ngraph/frontend/onnx_import/src/core/node.cpp index 4a90d1dbeb7..c45215ce72f 100644 --- a/ngraph/frontend/onnx_import/src/core/node.cpp +++ b/ngraph/frontend/onnx_import/src/core/node.cpp @@ -44,6 +44,10 @@ namespace ngraph bool has_attribute(const std::string& name) const; + Subgraph get_subgraph_from_attribute( + const std::string& name, + const std::map& carried_dependencies_map) const; + template T get_attribute_value(const std::string& name, T default_value) const; @@ -90,6 +94,21 @@ namespace ngraph return it != std::end(m_attributes); } + Subgraph Node::Impl::get_subgraph_from_attribute( + const std::string& name, + const std::map& carried_dependencies_map) const + { + auto it = std::find_if( + std::begin(m_attributes), std::end(m_attributes), [&](const Attribute& attribute) { + return attribute.get_name() == name; + }); + if (it == std::end(m_attributes)) + { + throw error::node::UnknownAttribute{this->name(), name}; + } + return it->get_subgraph(graph(), carried_dependencies_map); + } + template T Node::Impl::get_attribute_value(const std::string& name, T default_value) const { @@ -121,15 +140,8 @@ namespace ngraph template <> Subgraph Node::Impl::get_attribute_value(const std::string& name) const { - auto it = std::find_if( - std::begin(m_attributes), std::end(m_attributes), [&](const Attribute& attribute) { - return attribute.get_name() == name; - }); - if (it == std::end(m_attributes)) - { - throw error::node::UnknownAttribute{this->name(), name}; - } - return it->get_subgraph(graph()); + const std::map empty_map; + return get_subgraph_from_attribute(name, empty_map); } OutputVector Node::Impl::get_ng_nodes(const Node& node) const @@ -207,6 +219,13 @@ namespace ngraph return m_pimpl->has_attribute(name); } + Subgraph Node::get_subgraph_from_attribute( + const std::string& name, + const std::map& carried_dependencies_map) const + { + return m_pimpl->get_subgraph_from_attribute(name, carried_dependencies_map); + } + std::vector Node::get_attribute_names() const { std::vector attr_names; diff --git a/ngraph/frontend/onnx_import/src/op/loop.cpp b/ngraph/frontend/onnx_import/src/op/loop.cpp index 8d8c8c66057..23ded7464e2 100644 --- a/ngraph/frontend/onnx_import/src/op/loop.cpp +++ b/ngraph/frontend/onnx_import/src/op/loop.cpp @@ -70,7 +70,15 @@ namespace ngraph const OutputVector loop_carried_dependencies{std::next(ng_inputs.begin(), 2), ng_inputs.end()}; - const Subgraph& body_graph{node.get_attribute_value("body")}; + std::map loop_carried_dependencies_map; + for (std::size_t i = 0; i < loop_carried_dependencies.size(); i++) + { + loop_carried_dependencies_map[i + 2] = + loop_carried_dependencies[i].get_node()->get_friendly_name(); + } + + const Subgraph& body_graph{ + node.get_subgraph_from_attribute("body", loop_carried_dependencies_map)}; auto body_outputs = body_graph.get_ng_outputs(); const auto& body_inputs = body_graph.get_ng_parameters(); diff --git a/ngraph/frontend/onnx_import/src/utils/common.hpp b/ngraph/frontend/onnx_import/src/utils/common.hpp index 8e9f0b0c507..b386c002b07 100644 --- a/ngraph/frontend/onnx_import/src/utils/common.hpp +++ b/ngraph/frontend/onnx_import/src/utils/common.hpp @@ -125,6 +125,18 @@ namespace ngraph const std::shared_ptr input, const std::set allowed_types = {}); + /// \brief Temporary replacement for C++14 std::make_unique. + /// \note details: https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique + /// + /// \param args List of arguments with which an instance of T will be constructed. + /// + /// \return std::unique_ptr of an instance of type T + template + std::unique_ptr make_unique(Args&&... args) + { + return std::unique_ptr(new T(std::forward(args)...)); + } + } // namespace common } // namespace onnx_import } // namespace ngraph diff --git a/ngraph/frontend/onnx_import/src/utils/onnx_internal.cpp b/ngraph/frontend/onnx_import/src/utils/onnx_internal.cpp index 00544c1fabf..74bb4a72d5c 100644 --- a/ngraph/frontend/onnx_import/src/utils/onnx_internal.cpp +++ b/ngraph/frontend/onnx_import/src/utils/onnx_internal.cpp @@ -18,8 +18,10 @@ namespace ngraph std::shared_ptr convert_to_ng_function(const ONNX_NAMESPACE::ModelProto& model_proto) { - Model model{model_proto}; - Graph graph{model_proto.graph(), model}; + auto p_model_proto = common::make_unique(model_proto); + auto model = common::make_unique(std::move(p_model_proto)); + + Graph graph{std::move(model)}; auto function = std::make_shared( graph.get_ng_outputs(), graph.get_ng_parameters(), graph.get_name()); for (std::size_t i{0}; i < function->get_output_size(); ++i) diff --git a/ngraph/python/tests/test_onnx/test_backend.py b/ngraph/python/tests/test_onnx/test_backend.py index 32442b0a375..ebfd747406e 100644 --- a/ngraph/python/tests/test_onnx/test_backend.py +++ b/ngraph/python/tests/test_onnx/test_backend.py @@ -29,7 +29,6 @@ from tests import (BACKEND_NAME, xfail_issue_38722, xfail_issue_38723, xfail_issue_38724, - xfail_issue_38725, xfail_issue_38732, xfail_issue_38734, xfail_issue_38735, @@ -299,9 +298,6 @@ tests_expected_to_fail = [ "OnnxBackendNodeModelTest.test_qlinearconv_cpu"), (xfail_issue_38724, "OnnxBackendNodeModelTest.test_resize_tf_crop_and_resize_cpu"), - (xfail_issue_38725, - "OnnxBackendNodeModelTest.test_range_int32_type_negative_delta_expanded_cpu", - "OnnxBackendNodeModelTest.test_range_float_type_positive_delta_expanded_cpu"), (xfail_issue_33512, "OnnxBackendNodeModelTest.test_einsum_transpose_cpu", "OnnxBackendNodeModelTest.test_einsum_batch_diagonal_cpu", @@ -359,7 +355,9 @@ tests_expected_to_fail = [ "OnnxBackendNodeModelTest.test_unsqueeze_two_axes_cpu", "OnnxBackendNodeModelTest.test_unsqueeze_unsorted_axes_cpu",), (xfail_issue_44956, - "OnnxBackendNodeModelTest.test_loop11_cpu"), + "OnnxBackendNodeModelTest.test_loop11_cpu", + "OnnxBackendNodeModelTest.test_range_int32_type_negative_delta_expanded_cpu", + "OnnxBackendNodeModelTest.test_range_float_type_positive_delta_expanded_cpu"), (xfail_issue_44957, "OnnxBackendNodeModelTest.test_compress_0_cpu", "OnnxBackendNodeModelTest.test_compress_1_cpu", diff --git a/ngraph/test/models/onnx/loop/loop_add_node_from_parent_scope_infer_types.prototxt b/ngraph/test/models/onnx/loop/loop_add_node_from_parent_scope_infer_types.prototxt new file mode 100644 index 00000000000..0577bf5d0ef --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_add_node_from_parent_scope_infer_types.prototxt @@ -0,0 +1,176 @@ +ir_version: 6 +producer_name: "nGraph ONNX Importer" +graph { + name: "basic loop" + node { + input: "parent_input" + input: "scale" + name: "mul_node" + op_type: "Mul" + output: "b" + } + node { + input: "parent_input" + input: "b" + name: "parent_add_node" + op_type: "Add" + output: "c" + } + node { + input: "trip_count" + input: "cond_in" + input: "a_init" + output: "a_final" + output: "a_values" + op_type: "Loop" + attribute { + name: "body" + g { + name: "simple add" + node { + input: "b" + input: "a_in" + output: "current_a" + name: "loop_body_add" + op_type: "Add" + } + node { + input: "cond" + output: "cond_out" + name: "cond_identity" + op_type: "Identity" + } + node { + input: "current_a" + output: "a_out" + name: "output_accumulator" + op_type: "Identity" + } + input { + name: "i" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond" + type { + tensor_type { + elem_type: 9 + } + } + } + input { + name: "a_in" + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + } + } + } + output { + name: "current_a" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_out" + type { + tensor_type { + elem_type: 1 + } + } + } + } + type: GRAPH + } + } + initializer { + dims: 1 + data_type: 7 + int64_data: 3 + name: "trip_count" + } + initializer { + dims: 1 + data_type: 9 + int32_data: 00000001 + name: "cond_in" + } + initializer { + dims: 1 + data_type: 1 + float_data: 2 + name: "scale" + } + + input { + name: "a_init" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + input { + name: "parent_input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "a_final" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_values" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "c" + type { + tensor_type { + elem_type: 1 + } + } + } +} +opset_import { + version: 11 +} diff --git a/ngraph/test/models/onnx/loop/onnx_controlflow_loop_2d_infer_types.prototxt b/ngraph/test/models/onnx/loop/onnx_controlflow_loop_2d_infer_types.prototxt new file mode 100644 index 00000000000..a29f7d97980 --- /dev/null +++ b/ngraph/test/models/onnx/loop/onnx_controlflow_loop_2d_infer_types.prototxt @@ -0,0 +1,184 @@ +ir_version: 6 +producer_name: "nGraph ONNX Importer" +graph { + name: "basic loop" + node { + input: "trip_count" + input: "cond_in" + input: "a_init" + output: "a_final" + op_type: "Loop" + attribute { + name: "body" + g { + node { + input: "a_in" + input: "b" + output: "current_a" + name: "loop_body_add" + op_type: "Add" + } + node { + input: "i" + input: "threshold" + output: "cond_out" + name: "condition_calc" + op_type: "Less" + } + node { + input: "current_a" + output: "a_out" + name: "output_accumulator" + op_type: "Identity" + } + name: "simple add" + initializer { + dims: 1 + dims: 2 + data_type: 1 + float_data: 1 + float_data: 1 + name: "b" + } + input { + name: "i" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "a_in" + type { + tensor_type { + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "current_a" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + } + type: GRAPH + } + } + initializer { + dims: 1 + data_type: 7 + int64_data: 5 + name: "threshold" + } + input { + name: "trip_count" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond_in" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "a_init" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "a_final" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 11 +} diff --git a/ngraph/test/onnx/onnx_import_controlflow.in.cpp b/ngraph/test/onnx/onnx_import_controlflow.in.cpp index fa97cd42176..1eb5ab73f97 100644 --- a/ngraph/test/onnx/onnx_import_controlflow.in.cpp +++ b/ngraph/test/onnx/onnx_import_controlflow.in.cpp @@ -381,6 +381,49 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_trip_count_dynamic) test_case.run(); } +// ~~~~~~~~SUBGRAPH TYPES INFERENCE:~~~~~~~~ +NGRAPH_TEST(${BACKEND_NAME}, + onnx_controlflow_loop_2d_infer_types) +{ + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, + "onnx/loop/onnx_controlflow_loop_2d_infer_types.prototxt")); + + auto test_case = test::TestCase(function); + // trip count + test_case.add_input({10}); + + // termination condition + test_case.add_input({true}); + + // a_init + test_case.add_input({0.f, 0.f}); + + test_case.add_expected_output(Shape{1, 2}, {6.f, 6.f}); + test_case.run(); +} + + +NGRAPH_TEST(${BACKEND_NAME}, + onnx_controlflow_loop_add_node_from_parent_scope_infer_types) +{ + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, + "onnx/loop/loop_add_node_from_parent_scope_infer_types.prototxt")); + + auto test_case = test::TestCase(function); + // a_init + test_case.add_input({0.f, 0.f}); + // parent_input + test_case.add_input({3.f}); + + test_case.add_expected_output(Shape{1, 2}, {18.f, 18.f}); + test_case.add_expected_output(Shape{3, 1, 2}, {6.f, 6.f, 12.f, 12.f, 18.f, 18.f}); + test_case.add_expected_output(Shape{1}, {9.f}); + test_case.run(); +} + + // ~~~~~~~~ADDITIONAL TESTS:~~~~~~~~ NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_concat_values) From b17b526009e559a2bfd3099dc61e77ceccd81714 Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Wed, 12 May 2021 12:11:27 +0300 Subject: [PATCH 24/99] Add gather 7 to nG Python API and IE IR reader test (#5276) * nG Python api for Gather and IE IR reader tests * also included old IE IR reader test for Gather1 * added a blank line before Gather * style corrections * applied review comments * removed blank line * removed xfailed for Gather7 with batch_dims since CPU was moved to nGraph (...allows to fallback node execution on ngraph evaluate() method in case if optimized implementation is absent) * added new visitor tests --- .../ngraph_reader/gather_tests.cpp | 137 +++++++++++++++++- ngraph/python/src/ngraph/opset6/ops.py | 2 +- ngraph/python/src/ngraph/opset7/__init__.py | 2 +- ngraph/python/src/ngraph/opset7/ops.py | 21 +++ ngraph/python/tests/__init__.py | 1 - .../python/tests/test_ngraph/test_gather.py | 54 +++++++ .../tests/test_ngraph/test_ops_reshape.py | 17 +-- ngraph/test/CMakeLists.txt | 1 + ngraph/test/visitors/op/gather.cpp | 31 ++++ 9 files changed, 242 insertions(+), 24 deletions(-) create mode 100644 ngraph/python/tests/test_ngraph/test_gather.py create mode 100644 ngraph/test/visitors/op/gather.cpp diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/gather_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/gather_tests.cpp index f44528a9d14..f38aecfe185 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/gather_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/gather_tests.cpp @@ -4,7 +4,8 @@ #include #include "ngraph_reader_tests.hpp" -TEST_F(NGraphReaderTests, ReadGatherNetwork) { + +TEST_F(NGraphReaderTests, Read_Gather1_Network) { std::string model = R"V0G0N( @@ -117,7 +118,133 @@ TEST_F(NGraphReaderTests, ReadGatherNetwork) { )V0G0N"; compareIRs(model, modelV7, 16, [](Blob::Ptr& weights) { - auto* buffer = weights->buffer().as(); - buffer[0] = 0; - }); -} \ No newline at end of file + auto* buffer = weights->buffer().as(); + buffer[0] = 0; + }); +} + +TEST_F(NGraphReaderTests, Read_Gather7_Network) { + std::string model = R"V0G0N( + + + + + + + 2 + 3 + 4 + + + + + + + + 8 + 16 + + + + + + + + + + + + + + 2 + 3 + 4 + + + 8 + 16 + + + + + + 2 + 8 + 16 + 4 + + + + + + + 2 + 8 + 16 + 4 + + + + + + + + + + + +)V0G0N"; + std::string modelV7 = R"V0G0N( + + + + + + 2 + 3 + 4 + + + + + + + 8 + 16 + + + + + + + + 2 + 3 + 4 + + + 8 + 16 + + + + + 2 + 8 + 16 + 4 + + + + + + + + + +)V0G0N"; + compareIRs(model, modelV7, 8, [](Blob::Ptr& weights) { + auto* buffer = weights->buffer().as(); + buffer[0] = 1; + }); +} diff --git a/ngraph/python/src/ngraph/opset6/ops.py b/ngraph/python/src/ngraph/opset6/ops.py index 7260a6fdcf9..415ba6b5db2 100644 --- a/ngraph/python/src/ngraph/opset6/ops.py +++ b/ngraph/python/src/ngraph/opset6/ops.py @@ -84,7 +84,7 @@ def gather_elements( axis: Optional[int] = 0, name: Optional[str] = None, ) -> Node: - """Return a node which performs GatherND. + """Return a node which performs GatherElements. @param data: N-D tensor with data for gathering @param indices: N-D tensor with indices by which data is gathered diff --git a/ngraph/python/src/ngraph/opset7/__init__.py b/ngraph/python/src/ngraph/opset7/__init__.py index 4b7e715982b..08a24529d41 100644 --- a/ngraph/python/src/ngraph/opset7/__init__.py +++ b/ngraph/python/src/ngraph/opset7/__init__.py @@ -51,7 +51,7 @@ from ngraph.opset1.ops import exp from ngraph.opset1.ops import fake_quantize from ngraph.opset1.ops import floor from ngraph.opset1.ops import floor_mod -from ngraph.opset1.ops import gather +from ngraph.opset7.ops import gather from ngraph.opset6.ops import gather_elements from ngraph.opset5.ops import gather_nd from ngraph.opset1.ops import gather_tree diff --git a/ngraph/python/src/ngraph/opset7/ops.py b/ngraph/python/src/ngraph/opset7/ops.py index a2b0c26930f..d8b4325adcd 100644 --- a/ngraph/python/src/ngraph/opset7/ops.py +++ b/ngraph/python/src/ngraph/opset7/ops.py @@ -104,6 +104,27 @@ def roll( @nameable_op +def gather( + data: NodeInput, + indices: NodeInput, + axis: NodeInput, + batch_dims: Optional[int] = 0, +) -> Node: + """Return a node which performs Gather. + + @param data: N-D tensor with data for gathering + @param indices: N-D tensor with indices by which data is gathered + @param axis: axis along which elements are gathered + @param batch_dims: number of batch dimensions + @return: The new node which performs Gather + """ + inputs = as_nodes(data, indices, axis) + attributes = { + "batch_dims": batch_dims + } + return _get_node_factory_opset7().create("Gather", inputs, attributes) + + def dft( data: NodeInput, axes: NodeInput, diff --git a/ngraph/python/tests/__init__.py b/ngraph/python/tests/__init__.py index 21a44177a6f..3fd4136dd3c 100644 --- a/ngraph/python/tests/__init__.py +++ b/ngraph/python/tests/__init__.py @@ -157,7 +157,6 @@ xfail_issue_52463 = xfail_test(reason="test_operator_add_size1_singleton_broadca "Not equal to tolerance") xfail_issue_49391 = xfail_test(reason="Roll is not implemented in CPU plugin.") - xfail_issue_49359 = xfail_test(reason="DFT is not implemented in CPU plugin") xfail_issue_49375 = xfail_test(reason="IDFT is not implemented in CPU plugin") xfail_issue_45432 = xfail_test(reason="Einsum is not implemented in CPU plugin.") diff --git a/ngraph/python/tests/test_ngraph/test_gather.py b/ngraph/python/tests/test_ngraph/test_gather.py new file mode 100644 index 00000000000..08ff0893a8f --- /dev/null +++ b/ngraph/python/tests/test_ngraph/test_gather.py @@ -0,0 +1,54 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import ngraph as ng +import numpy as np + +from tests.test_ngraph.util import run_op_node + + +def test_gather(): + input_data = np.array( + [1.0, 1.1, 1.2, 2.0, 2.1, 2.2, 3.0, 3.1, 3.2], np.float32 + ).reshape((3, 3)) + input_indices = np.array([0, 2], np.int32).reshape(1, 2) + input_axis = np.array([1], np.int32) + + expected = np.array([1.0, 1.2, 2.0, 2.2, 3.0, 3.2], dtype=np.float32).reshape( + (3, 1, 2) + ) + + result = run_op_node([input_data], ng.gather, input_indices, input_axis) + assert np.allclose(result, expected) + + +def test_gather_with_scalar_axis(): + input_data = np.array( + [1.0, 1.1, 1.2, 2.0, 2.1, 2.2, 3.0, 3.1, 3.2], np.float32 + ).reshape((3, 3)) + input_indices = np.array([0, 2], np.int32).reshape(1, 2) + input_axis = np.array(1, np.int32) + + expected = np.array([1.0, 1.2, 2.0, 2.2, 3.0, 3.2], dtype=np.float32).reshape( + (3, 1, 2) + ) + + result = run_op_node([input_data], ng.gather, input_indices, input_axis) + assert np.allclose(result, expected) + + +def test_gather_batch_dims_1(): + + input_data = np.array([[1, 2, 3, 4, 5], + [6, 7, 8, 9, 10]], np.float32) + + input_indices = np.array([[0, 0, 4], + [4, 0, 0]], np.int32) + input_axis = np.array([1], np.int32) + batch_dims = 1 + + expected = np.array([[1, 1, 5], + [10, 6, 6]], np.float32) + + result = run_op_node([input_data], ng.gather, input_indices, input_axis, batch_dims) + assert np.allclose(result, expected) diff --git a/ngraph/python/tests/test_ngraph/test_ops_reshape.py b/ngraph/python/tests/test_ngraph/test_ops_reshape.py index 85ec57739fb..8930c49ffc5 100644 --- a/ngraph/python/tests/test_ngraph/test_ops_reshape.py +++ b/ngraph/python/tests/test_ngraph/test_ops_reshape.py @@ -1,10 +1,10 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +import ngraph as ng import numpy as np import pytest -import ngraph as ng from tests.runtime import get_runtime from tests.test_ngraph.util import run_op_node, run_op_numeric_data @@ -120,21 +120,6 @@ def test_broadcast_bidirectional(): assert node.get_output_size() == 1 -def test_gather(): - input_data = np.array( - [1.0, 1.1, 1.2, 2.0, 2.1, 2.2, 3.0, 3.1, 3.2], np.float32 - ).reshape((3, 3)) - input_indices = np.array([0, 2], np.int32).reshape(1, 2) - input_axes = np.array([1], np.int32) - - expected = np.array([1.0, 1.2, 2.0, 2.2, 3.0, 3.2], dtype=np.float32).reshape( - (3, 1, 2) - ) - - result = run_op_node([input_data], ng.gather, input_indices, input_axes) - assert np.allclose(result, expected) - - def test_transpose(): input_tensor = np.arange(3 * 3 * 224 * 224, dtype=np.int32).reshape( (3, 3, 224, 224) diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 07d2632172e..d4aabfccf8a 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -219,6 +219,7 @@ set(SRC visitors/op/elu.cpp visitors/op/extractimagepatches.cpp visitors/op/fake_quantize.cpp + visitors/op/gather.cpp visitors/op/grn.cpp visitors/op/group_conv.cpp visitors/op/interpolate.cpp diff --git a/ngraph/test/visitors/op/gather.cpp b/ngraph/test/visitors/op/gather.cpp new file mode 100644 index 00000000000..3e6446a07b8 --- /dev/null +++ b/ngraph/test/visitors/op/gather.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" + +#include "ngraph/ngraph.hpp" +#include "ngraph/opsets/opset1.hpp" +#include "ngraph/opsets/opset7.hpp" + +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(attributes, gather_v7_op) +{ + NodeBuilder::get_ops().register_factory(); + auto data = make_shared(element::i32, Shape{2, 3, 4}); + auto indices = make_shared(element::i32, Shape{2}); + auto axis = make_shared(element::i32, Shape{}, 2); + int64_t batch_dims = 1; + + auto gather = make_shared(data, indices, axis, batch_dims); + NodeBuilder builder(gather); + auto g_gather = as_type_ptr(builder.create()); + + EXPECT_EQ(g_gather->get_batch_dims(), gather->get_batch_dims()); +} From 6ecadc1548f78accb8921e0e1f1c2867d59b0d0e Mon Sep 17 00:00:00 2001 From: Taylor Yeonbok Lee Date: Wed, 12 May 2021 18:33:24 +0900 Subject: [PATCH 25/99] [IE CLDNN] Add description for new CLDNN plugin configuration MAX_NUM_THREADS (#5582) --- docs/IE_DG/supported_plugins/CL_DNN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/IE_DG/supported_plugins/CL_DNN.md b/docs/IE_DG/supported_plugins/CL_DNN.md index ea32d2d8cee..995d3da746e 100644 --- a/docs/IE_DG/supported_plugins/CL_DNN.md +++ b/docs/IE_DG/supported_plugins/CL_DNN.md @@ -116,7 +116,7 @@ When specifying key values as raw strings (that is, when using Python API), omit | `KEY_CLDNN_SOURCES_DUMPS_DIR` | `""` | `""` | Final optimized clDNN OpenCL sources dump output directory | | `KEY_GPU_THROUGHPUT_STREAMS` | `KEY_GPU_THROUGHPUT_AUTO`, or positive integer| 1 | Specifies a number of GPU "execution" streams for the throughput mode (upper bound for a number of inference requests that can be executed simultaneously).
This option is can be used to decrease GPU stall time by providing more effective load from several streams. Increasing the number of streams usually is more effective for smaller topologies or smaller input sizes. Note that your application should provide enough parallel slack (e.g. running many inference requests) to leverage full GPU bandwidth. Additional streams consume several times more GPU memory, so make sure the system has enough memory available to suit parallel stream execution. Multiple streams might also put additional load on CPU. If CPU load increases, it can be regulated by setting an appropriate `KEY_CLDNN_PLUGIN_THROTTLE` option value (see above). If your target system has relatively weak CPU, keep throttling low.
The default value is 1, which implies latency-oriented behavior.
`KEY_GPU_THROUGHPUT_AUTO` creates bare minimum of streams to improve the performance; this is the most portable option if you are not sure how many resources your target machine has (and what would be the optimal number of streams).
A positive integer value creates the requested number of streams. | | `KEY_EXCLUSIVE_ASYNC_REQUESTS` | `YES` / `NO` | `NO` | Forces async requests (also from different executable networks) to execute serially.| - +| `KEY_CLDNN_MAX_NUM_THREADS` | `integer value` | `maximum # of HW threads available in host environment` | Specifies the number of CPU threads that can be used for clDNN engine, e.g, JIT compilation of clDNN kernels or clDNN cpu kernel processing. The default value is set as the number of maximum available threads in host environment to minimize the time for LoadNetwork, where the clDNN kernel build time occupies a large portion. Note that if the specified value is larger than the maximum available # of threads or less than zero, it is set as maximum available # of threads. It can be specified with a smaller number than the available HW threads according to the usage scenario, e.g., when the user wants to assign more CPU threads while clDNN plugin is running. Note that setting this value with lower number will affect not only the network loading time but also the cpu layers of clDNN networks that are optimized with multi-threading. | ## Note on Debug Capabilities of the GPU Plugin Inference Engine GPU plugin provides possibility to dump the user custom OpenCL™ kernels to a file to allow you to properly debug compilation issues in your custom kernels. From c76c0eb39e38f2d470b0283911081af31e000d54 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 12 May 2021 12:57:48 +0300 Subject: [PATCH 26/99] Moved ie_tests to legacy (#5561) * Removed obsolete tests files * Removed old SLT * Moved ie_tests to legacy --- .../functional_test_utils/CMakeLists.txt | 1 - .../tests_deprecated/behavior/CMakeLists.txt | 2 +- .../functional/CMakeLists.txt | 1 - .../functional/cldnn/CMakeLists.txt | 62 +- .../functional/gna/CMakeLists.txt | 1 + .../functional/ie_tests/CMakeLists.txt | 36 - .../ie_tests/include/base_matcher.hpp | 30 - .../include/classification_matcher.hpp | 43 -- .../ie_tests/include/custom_matcher.hpp | 80 --- .../ie_tests/include/label_probability.hpp | 70 -- .../functional/ie_tests/include/net_model.hpp | 39 - .../include/object_detection_matcher.hpp | 127 ---- .../include/optimized_network_matcher.hpp | 58 -- .../ie_tests/include/raw_matcher.hpp | 35 - .../ie_tests/include/regression_config.hpp | 186 ----- .../ie_tests/include/regression_reference.hpp | 24 - .../ie_tests/include/regression_tests.hpp | 678 ------------------ .../ie_tests/include/segmentation_matcher.hpp | 75 -- .../functional/ie_tests/src/base_matcher.cpp | 118 --- .../ie_tests/src/classification_matcher.cpp | 297 -------- .../ie_tests/src/custom_matcher.cpp | 430 ----------- .../functional/ie_tests/src/net_model.cpp | 19 - .../ie_tests/src/object_detection_matcher.cpp | 278 ------- .../src/optimized_network_matcher.cpp | 66 -- .../functional/ie_tests/src/raw_matcher.cpp | 363 ---------- .../ie_tests/src/segmentation_matcher.cpp | 239 ------ .../functional/mkldnn/CMakeLists.txt | 53 +- .../functional/mkldnn/dummy.cpp | 1 - .../functional/shared_tests/CMakeLists.txt | 10 +- .../common_single_layer_tests/pool_ref.hpp | 3 +- .../single_layer_tests.hpp | 2 + .../graph_tools_functional_tests.hpp | 37 - .../common_dyn_batch_regression.hpp | 90 --- .../shared_tests/input_tests/parser_tests.hpp | 1 - .../io_blob_tests/cropResize_tests.hpp | 1 - .../shared_tests/lstm/lstm_ir_test.hpp | 91 --- .../single_layer_tests/bin_conv_tests.hpp | 425 ----------- .../deformable_psroi_tests.hpp | 330 --------- .../single_layer_tests/gemm_tests.hpp | 492 ------------- .../single_layer_tests/one_hot_tests.hpp | 208 ------ .../single_layer_tests/permute_tests.hpp | 168 ----- .../single_layer_tests/quantize_tests.hpp | 331 --------- .../single_layer_tests/reduce_tests.hpp | 402 ----------- .../single_layer_tests/resample_tests.hpp | 269 ------- .../single_layer_tests/ti_tests.hpp | 2 - .../functional/vpu/CMakeLists.txt | 4 + .../helpers/reference_regression.cpp | 22 +- .../regression/helpers/vpu_case_common.hpp | 8 +- .../regression/helpers/vpu_case_params.hpp | 36 +- .../helpers/vpu_classification_case.cpp | 1 + .../helpers/vpu_classification_case.hpp | 5 +- .../helpers/vpu_raw_results_case.cpp | 3 + .../vpu/vpu_base/myriad_layers_tests.hpp | 1 + .../tests_deprecated/helpers/CMakeLists.txt | 5 + .../src => helpers}/ie_core_adapter.cpp | 0 .../include => helpers}/ie_core_adapter.hpp | 0 .../helpers/ir_gen_helper.cpp | 81 --- .../helpers/ir_gen_helper.hpp | 40 -- .../helpers/tests_common_func.cpp | 267 ------- .../helpers/tests_common_func.hpp | 89 --- .../unit/engines/mkldnn/dummy.cpp | 4 - 61 files changed, 51 insertions(+), 6789 deletions(-) delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/CMakeLists.txt delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/base_matcher.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/classification_matcher.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/custom_matcher.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/label_probability.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/net_model.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/object_detection_matcher.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/optimized_network_matcher.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/raw_matcher.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/regression_config.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/regression_reference.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/regression_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/include/segmentation_matcher.hpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/src/base_matcher.cpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/src/classification_matcher.cpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/src/custom_matcher.cpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/src/net_model.cpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/src/object_detection_matcher.cpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/src/optimized_network_matcher.cpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/src/raw_matcher.cpp delete mode 100644 inference-engine/tests_deprecated/functional/ie_tests/src/segmentation_matcher.cpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/graph_tools/graph_tools_functional_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/inference_engine_regression_tests/common_dyn_batch_regression.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/lstm/lstm_ir_test.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/bin_conv_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/deformable_psroi_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/gemm_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/one_hot_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/permute_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/quantize_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/reduce_tests.hpp delete mode 100644 inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/resample_tests.hpp rename inference-engine/tests_deprecated/{functional/ie_tests/src => helpers}/ie_core_adapter.cpp (100%) rename inference-engine/tests_deprecated/{functional/ie_tests/include => helpers}/ie_core_adapter.hpp (100%) delete mode 100644 inference-engine/tests_deprecated/helpers/ir_gen_helper.cpp delete mode 100644 inference-engine/tests_deprecated/helpers/ir_gen_helper.hpp delete mode 100644 inference-engine/tests_deprecated/helpers/tests_common_func.cpp delete mode 100644 inference-engine/tests_deprecated/helpers/tests_common_func.hpp delete mode 100644 inference-engine/tests_deprecated/unit/engines/mkldnn/dummy.cpp diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/CMakeLists.txt b/inference-engine/tests/ie_test_utils/functional_test_utils/CMakeLists.txt index f391e1ce202..6ed92869536 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/CMakeLists.txt +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/CMakeLists.txt @@ -37,4 +37,3 @@ addIeTarget( ie_faster_build(${TARGET_NAME} PCH PRIVATE "src/precomp.hpp" ) - diff --git a/inference-engine/tests_deprecated/behavior/CMakeLists.txt b/inference-engine/tests_deprecated/behavior/CMakeLists.txt index 8b32bf5c19d..0cdfeb9f891 100644 --- a/inference-engine/tests_deprecated/behavior/CMakeLists.txt +++ b/inference-engine/tests_deprecated/behavior/CMakeLists.txt @@ -8,4 +8,4 @@ disable_deprecated_warnings() if (ENABLE_HDDL OR ENABLE_MYRIAD) add_subdirectory(vpu) -endif() \ No newline at end of file +endif() diff --git a/inference-engine/tests_deprecated/functional/CMakeLists.txt b/inference-engine/tests_deprecated/functional/CMakeLists.txt index 8ee3016d989..d6bf3a0d281 100644 --- a/inference-engine/tests_deprecated/functional/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/CMakeLists.txt @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # -add_subdirectory(ie_tests) add_subdirectory(shared_tests) disable_deprecated_warnings() diff --git a/inference-engine/tests_deprecated/functional/cldnn/CMakeLists.txt b/inference-engine/tests_deprecated/functional/cldnn/CMakeLists.txt index 223bf1635f3..6c834d0723e 100644 --- a/inference-engine/tests_deprecated/functional/cldnn/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/cldnn/CMakeLists.txt @@ -2,64 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # -set(TARGET_NAME ClDnnFunctionalTests) +add_executable(ClDnnFunctionalTests dummy.cpp) -file(GLOB CLDNN_TEST_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) - -list(APPEND TEST_SRC ${CLDNN_TEST_SOURCES}) - -list(APPEND CLDNN_LIBS - IESharedTests - ${CLDNN__OCL_ICD_LIBPATH}) - -# try to find VA libraries -find_package(PkgConfig QUIET) -if(PkgConfig_FOUND) - pkg_search_module(LIBVA QUIET libva) -endif() - -# TODO: pkg_search_module finds libva not in sysroot -if(ANDROID) - set(LIBVA_FOUND OFF CACHE BOOL "" FORCE) -endif() - -if(LIBVA_FOUND) - list(APPEND CLDNN_LIBS ${LIBVA_LINK_LIBRARIES}) -endif() - -list(APPEND DEPENDENCIES - clDNNPlugin) - -if (ENABLE_MKL_DNN) - list(APPEND DEPENDENCIES - MKLDNNPlugin - HeteroPlugin) -endif() - -# add OpenCL dependency end - -source_group("src" FILES ${TEST_SRC}) -source_group("include" FILES ${TEST_INCLUDE}) - -add_executable(${TARGET_NAME} - ${TEST_SRC} - ${TEST_INCLUDE}) - -target_compile_definitions(${TARGET_NAME} - PUBLIC ${ARGV} - DATA_PATH=\"${DATA_PATH}\" - MODELS_PATH=\"${MODELS_PATH}\") - -if(LIBVA_FOUND) - target_compile_definitions(${TARGET_NAME} PRIVATE ENABLE_LIBVA) - target_include_directories(${TARGET_NAME} PRIVATE ${LIBVA_INCLUDE_DIRS}) -endif() - -target_include_directories(${TARGET_NAME} PRIVATE ${CLDNN__OCL_ICD_INCDIRS}) -target_link_libraries(${TARGET_NAME} PRIVATE ${CLDNN_LIBS}) - -add_dependencies(${TARGET_NAME} ${DEPENDENCIES}) - -add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME}) -set_property(TEST ${TARGET_NAME} PROPERTY LABELS GPU) +target_link_libraries(ClDnnFunctionalTests PRIVATE gtest_main) diff --git a/inference-engine/tests_deprecated/functional/gna/CMakeLists.txt b/inference-engine/tests_deprecated/functional/gna/CMakeLists.txt index a09b7cf91a3..564504b5f78 100644 --- a/inference-engine/tests_deprecated/functional/gna/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/gna/CMakeLists.txt @@ -41,6 +41,7 @@ target_compile_definitions(${TARGET_NAME} target_link_libraries(${TARGET_NAME} PRIVATE IESharedTests + funcTestUtils ) target_include_directories(${TARGET_NAME} diff --git a/inference-engine/tests_deprecated/functional/ie_tests/CMakeLists.txt b/inference-engine/tests_deprecated/functional/ie_tests/CMakeLists.txt deleted file mode 100644 index dc247e8a817..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# - -set(TARGET_NAME ie_tests) - -file(GLOB TEST_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp) -file(GLOB TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) - -# create target - -add_library(${TARGET_NAME} STATIC ${TEST_INCLUDE} ${TEST_SRC}) - -ie_faster_build(${TARGET_NAME} - UNITY -) - -list(APPEND EXPORT_DEPENDENCIES - funcTestUtils - ieTestHelpers - ) - -target_include_directories(${TARGET_NAME} - PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" - PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" - $) - -target_link_libraries(${TARGET_NAME} PUBLIC - format_reader - ${EXPORT_DEPENDENCIES} - ) - -# developer package - -openvino_developer_export_targets(COMPONENT inference_engine_tests - TARGETS ${TARGET_NAME} ${EXPORT_DEPENDENCIES} ieTestHelpers_s) diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/base_matcher.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/base_matcher.hpp deleted file mode 100644 index 84d2a5e6c37..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/base_matcher.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include "regression_config.hpp" -#include - -namespace Regression { namespace Matchers { - -using namespace InferenceEngine; - -class BaseMatcher { -protected: - RegressionConfig config; -public: - explicit BaseMatcher(const RegressionConfig &config) : config(config) { -#ifndef NDEBUG - std::cout << "Matching on " << config._device_name << std::endl; -#endif - } - - void checkImgNumber(int dynBatch = -1); -}; - -void loadImage(const std::string &imageFilename, InferenceEngine::Blob::Ptr &blob, bool bgr = true, int batchNumber = 1); - -} // namepspace Matchers -} // namespace Regression diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/classification_matcher.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/classification_matcher.hpp deleted file mode 100644 index 0b9b0ee81d1..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/classification_matcher.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include "base_matcher.hpp" -#include "regression_reference.hpp" -#include -#include "label_probability.hpp" - -namespace Regression { namespace Matchers { - -// this is one more version of classification matcher for new api of async/sync requests -class ClassificationMatcher : public BaseMatcher { -private: - size_t checkResultNumber; - std::vector _executableNetworks; - std::vector > _results; - ResponseDesc _resp; - InferenceEngine::InputsDataMap _inputsInfo; - InferenceEngine::OutputsDataMap _outputsInfo; - public: - explicit ClassificationMatcher(RegressionConfig &config); - void to(std::string modelType); - void to(const std::vector &expected); - - - private: - void readLabels(std::string labelFilePath); - int getIndexByLabel(const std::string &label); - std::string getLabel(unsigned int index); - void checkResult(size_t checkNumber, - const std::vector &expected); - virtual void match(size_t top); - void match_n(size_t top, int index); - void saveResults(const std::vector &topIndexes, const std::vector &probs, size_t top); - - size_t top = 5; -}; - -} } // namespace matchers diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/custom_matcher.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/custom_matcher.hpp deleted file mode 100644 index 4225156dcaa..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/custom_matcher.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include "base_matcher.hpp" -#include -#include - -IE_SUPPRESS_DEPRECATED_START -namespace Regression { namespace Matchers { - -using namespace InferenceEngine; - -class CustomMatcher : public BaseMatcher { - protected: - InferenceEngine::CNNNetwork network; - InferenceContext ctx; - bool match_in_dctor = false; - int precision; - - public: - - explicit CustomMatcher(const RegressionConfig &config, bool match_in_dctor = false) - : BaseMatcher(config), - match_in_dctor(match_in_dctor), - precision(4) { - if (!match_in_dctor) { - matchCustom(); - checkResult(); - } - } - ~CustomMatcher() { - if (match_in_dctor) { - matchCustom(); - checkResult(); - } - } - - CustomMatcher& withAvgDelta(float value) { - BaseMatcher::config.nearAvgValue = value; - return *this; - } - - CustomMatcher& withDelta(float value) { - BaseMatcher::config.nearValue = value; - return *this; - } - - CustomMatcher& setPrecision(int precision) { - this->precision = precision; - return *this; - } - - void matchCustom(); - - template - inline bool isApproximatelyEqual(TReal a, TReal b, TReal tolerance = std::numeric_limits::epsilon()) - { - TReal diff = std::fabs(a - b); - if (diff <= tolerance) - return true; - - if (diff < std::fmax(std::fabs(a), std::fabs(b)) * tolerance) - return true; - - return false; - } - - void checkResult(); - - protected: - InferenceEngine::ExecutableNetwork createExecutableNetworkFromIR(); - InferenceEngine::ExecutableNetwork createExecutableNetworkFromAOT(); -}; - -} -} // namespace Matchers -IE_SUPPRESS_DEPRECATED_END diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/label_probability.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/label_probability.hpp deleted file mode 100644 index 18b8c931e08..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/label_probability.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include - -namespace Regression { -namespace Reference { - -/** - * @class LabelProbability - * @brief A LabelProbability represents predicted data in easy to use format - */ -class LabelProbability { -private: - /** - * @brief Index of current label - */ - int labelIdx = 0; - /** - * @brief Name of class from file with labels - */ - std::string className; - /** - * @brief The probability of prediction - */ - float probability = 0.0f; - -public: - /** - * @brief A constructor of InferenceResults class - * @param labelIdx - index of current label - * @param probability - the probability of prediction - * @param className - name of class from file with labels - * @return InferenceResults object - */ - LabelProbability(int labelIdx, float probability, std::string className) : labelIdx(labelIdx), - className(className), - probability(probability) {} - - /** - * @brief Gets label index - * @return index of current label - */ - const int &getLabelIndex() const { - return labelIdx; - } - - /** - * @brief Gets label name - * @return label - */ - const std::string &getLabel() const { - return className; - } - - /** - * @brief Gets probability - * @return probability - */ - const float &getProbability() const { - return probability; - } -}; - -} // namespace Reference -} // namespace Regression - diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/net_model.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/net_model.hpp deleted file mode 100644 index a96ead95cfd..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/net_model.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include - -//------------------------------------------------------------------------------ -// class Model -//------------------------------------------------------------------------------ - -class Model { -public: - //Constructors - Model() = default; - explicit Model(const char *that) { - fileName_ = folderName_ = that; - } - - Model(const std::string &folderName, - const std::string &fileName, - const std::string &resolution, - const std::string & extension = "xml"); - - // Accessors - inline std::string folderName() const { return folderName_; }; - inline std::string fileName() const { return fileName_; }; - inline std::string resolution() const { return resolutionName_; }; - inline std::string extension() const { return extensionName_; }; - -private: - std::string folderName_; - std::string fileName_; - std::string resolutionName_; - std::string extensionName_; -}; - diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/object_detection_matcher.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/object_detection_matcher.hpp deleted file mode 100644 index e862e024c93..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/object_detection_matcher.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include "base_matcher.hpp" -#include - -namespace Regression { -namespace Matchers { -//------------------------------------------------------------------------------ -// class ObjectDetectionMatcher -//------------------------------------------------------------------------------ - -class ObjectDetectionMatcher : public BaseMatcher { - -public: - //Helpers - struct DetectedObject; - class ImageDescription; - class NetworkAdapter; - - using ImageDescriptionPtrVect = std::vector>; - using ScoreFunction = std::function; - - //Constructor - ObjectDetectionMatcher(const RegressionConfig &config); - - //Operations - virtual void match(const ScoreFunction&); - void checkResult(const std::vector& desired); - - void to(const ImageDescription &desired, const std::shared_ptr& adapter); - void to(const std::vector& desired, const std::shared_ptr& adapter); - - void to(const ImageDescription &desired, const NetworkAdapter& adapter); - void to(const std::vector& desired, const NetworkAdapter& adapter); - -private: - //Operations - void to(const std::vector& desired, const ScoreFunction&); - //Data section - ImageDescriptionPtrVect res_desc_; -}; - -using DetectedObject = ObjectDetectionMatcher::DetectedObject; -using ImageDescription = ObjectDetectionMatcher::ImageDescription; -using NetworkAdapter = ObjectDetectionMatcher::NetworkAdapter; - -//------------------------------------------------------------------------------ -// class DetectedObject -//------------------------------------------------------------------------------ - -struct ObjectDetectionMatcher::DetectedObject { - //Data section - int objectType; - float xmin, xmax, ymin, ymax, prob; - - //Constructors - DetectedObject(int objectType, float xmin, float ymin, float xmax, float ymax, float prob, int = -1); - DetectedObject(const DetectedObject& other); - - static float ioU(const DetectedObject& detected_object_1_, const DetectedObject& detected_object_2_); - - //Operations - void printObj(); -}; - -//------------------------------------------------------------------------------ -// class ImageDescription -//------------------------------------------------------------------------------ - -class ObjectDetectionMatcher::ImageDescription { -public: - // Constructors - ImageDescription(bool check_probs = false); - ImageDescription(const std::list &alist, bool check_probs = false); - ImageDescription(const ImageDescription& obj); - - //Operations - static float ioUMultiple(const ImageDescription &detected_objects, const ImageDescription &desired_objects); - void addDetectedObject(const DetectedObject& detected_obj); - - // Accessors - inline bool checkProbs() const; -public: - //Data section - std::list alist; - -private: - //Data section - bool check_probs_; -}; - -//------------------------------------------------------------------------------ -// class NetworkAdapter -//------------------------------------------------------------------------------ - -class ObjectDetectionMatcher::NetworkAdapter { -public: - //Operations - virtual std::vector> score(InferenceEngine::CNNNetwork network, - std::shared_ptr ie, - const std::string& deviceName, - const std::map& config, - const std::vector& images_files_names, - bool with_reshape = false, - bool useExportImport = false) const = 0; - - //Destructor - virtual ~NetworkAdapter() = default; -}; - -//------------------------------------------------------------------------------ -// Implementation of methods of class ImageDescription -//------------------------------------------------------------------------------ - -inline bool ImageDescription::checkProbs() const { - return check_probs_; -} - -} // namespace matchers -} // namespace regression \ No newline at end of file diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/optimized_network_matcher.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/optimized_network_matcher.hpp deleted file mode 100644 index a47d52b3884..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/optimized_network_matcher.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include "custom_matcher.hpp" - -namespace Regression { namespace Matchers { - -using namespace InferenceEngine; - -class OptimizedNetworkMatcher : public CustomMatcher { - protected: - std::string path_to_reference_dump; - std::vector firmware; - InferenceEngine::ExecutableNetwork executableApi; - public: - - explicit OptimizedNetworkMatcher(const RegressionConfig &config) - : CustomMatcher(config, true) { - } - ~OptimizedNetworkMatcher() { - if (match_in_dctor) { - matchCustom(); - checkResult(); - //not allow base matcher to match one more time - match_in_dctor = false; - } - } - - void matchCustom(); - - void to(std::string path_to_reference_dump); - std::vector readDumpFromFile(std::string path); - void checkResult(); -}; - -class OptimizedNetworkDumper : public OptimizedNetworkMatcher { - public: - using OptimizedNetworkMatcher::OptimizedNetworkMatcher; - - ~OptimizedNetworkDumper() { - if (match_in_dctor) { - dump(); - //not allow base matcher to match one more time - match_in_dctor = false; - } - } - - void match() {} - - void dump(); - -}; - -} // namespace Regression -} // namespace Matchers diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/raw_matcher.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/raw_matcher.hpp deleted file mode 100644 index cfd60ed8d5b..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/raw_matcher.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include "base_matcher.hpp" -#include - -namespace Regression { -namespace Matchers { - -class RawMatcher : public BaseMatcher { - InferenceEngine::BlobMap outputBlobs; -public: - RawMatcher(const RegressionConfig &config) - : BaseMatcher(config) { - } - - virtual void match(); - - void checkResult(const std::map> &allExpected); - - void to(const std::map> &allExpected) { - ASSERT_NO_FATAL_FAILURE(match()); - ASSERT_NO_FATAL_FAILURE(checkResult(allExpected)); - } - -}; - -} -} // namespace matchers diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/regression_config.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/regression_config.hpp deleted file mode 100644 index 1fde58a1fda..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/regression_config.hpp +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include - -#include -#include -#include - -namespace Regression { -using namespace std; - -class InferenceContext { - InferenceEngine::BlobMap _inputs; - std::vector _outputs; - std::vector _fileNames; - std::string _modelPath; - InferenceEngine::Precision _prec; - int _frameNumber = 0; - int _inputIndex = 0; - public: - std::string modelFilePath() const { - return _modelPath; - } - std::vector fileNames() const { - return _fileNames; - } - - void setModelPath(const std::string &path) { - _modelPath = path; - } - - void setModelPrecision(InferenceEngine::Precision prec) { - _prec = prec; - } - - InferenceEngine::Precision getModelPrecision() const { - return _prec; - } - - void setFileNames(const std::vector fileNames) { - _fileNames = fileNames; - } - - void setInput(std::string name, InferenceEngine::Blob::Ptr input) { - _inputs[name] = input; - } - - void setOutput(std::string name, InferenceEngine::Blob::Ptr output) { - - outputs()[name] = output; - } - - InferenceEngine::Blob::Ptr getOutput(std::string name) { - return outputs()[name]; - } - - const InferenceEngine::BlobMap& inputs() const { - return _inputs; - } - - const InferenceEngine::BlobMap& outputs() const { - return const_cast(this)->outputs(); - } - - std::vector& allOutputs() { - return _outputs; - } - - InferenceEngine::BlobMap& outputs() { - if (_outputs.empty()) { - _outputs.push_back(InferenceEngine::BlobMap()); - } - return _outputs.front(); - } - - InferenceEngine::BlobMap& newOutputs() { - _outputs.push_back(InferenceEngine::BlobMap()); - return _outputs.back(); - } - - void setFrameNumber(int num) { - _frameNumber = num; - } - - int getFrameNumber() const { - return _frameNumber; - } - - void setInputIdx(int num) { - _inputIndex = num; - } - - size_t getInputIdx() const { - return _inputIndex; - } - - std::string currentInputFile() const { - if (fileNames().empty()) { - return ""; - } - return fileNames()[std::min(getInputIdx(), fileNames().size()-1)]; - } - - const InferenceEngine::Blob::Ptr currentInputs() const { - auto input = _inputs.begin(); - std::advance(input, getInputIdx()); - return input->second; - } - -}; - -struct RegressionConfig { - struct InputFetcherResult { - bool reset = false; - bool fetchMore = false; - bool fetched = true; - int frameNumber = 0; - bool hasResult = true; - InputFetcherResult() = default; - InputFetcherResult(bool reset, bool fetchMore=false, bool fetched=true, int frameNumber = 0, bool hasResult = true) - : reset(reset), fetchMore(fetchMore), fetched(fetched), frameNumber(frameNumber), hasResult(hasResult) {} - }; - using input_fetcher = std::function; - using model_maker = std::function; - using result_fetcher = std::function; - - std::vector fetch_input; - result_fetcher fetch_result; - model_maker make_model; - string _path_to_models; - string _path_to_aot_model; - vector _paths_to_images; - string _device_name; - string _firmware; - string _tmp_firmware; - vector labels; - double nearValue = 0.0; - double nearAvgValue = 0.0; - double maxRelativeError = 0.0; - double meanRelativeError = 0.0; - bool batchMode = false; - bool compactMode = true; - bool int8Mode = false; - bool isAsync = false; - int batchSize = 1; - //number of async infer requests to create - int _nrequests = 1; - int topKNumbers = -1; - int _numNetworks = 1; - - bool useDynamicBatching = false; - int dynBatch = -1; - bool print = false; - bool useExportImport = false; - std::size_t printNum = 0; - - vector referenceOutput; - vector referenceBin; - - InferenceEngine::Blob::Ptr outputBlob; - std::string outputLayer; - InferenceEngine::Precision _inputPrecision; - InferenceEngine::Precision modelPrecision; - InferenceEngine::Precision _outputPrecision = InferenceEngine::Precision::UNSPECIFIED; - std::map _outputBlobPrecision; - std::map* perfInfoPtr = nullptr; - std::map plugin_config; - std::map deviceMapping; - - std::shared_ptr ie_core; - - bool _reshape = false; -}; - -enum InputFormat { - RGB = 0, - BGR = 1 -}; - -} diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/regression_reference.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/regression_reference.hpp deleted file mode 100644 index d743ad71372..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/regression_reference.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include "label_probability.hpp" - -namespace Regression { -namespace Reference { - -struct ClassificationScoringResultsForTests : public LabelProbability{ - ClassificationScoringResultsForTests(float prob, const std::string & label) - : LabelProbability(0, prob, label ){ - } -}; - -extern std::map> values; - -} // namespace Reference -} // namespace Regression diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/regression_tests.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/regression_tests.hpp deleted file mode 100644 index fc8db0deb2a..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/regression_tests.hpp +++ /dev/null @@ -1,678 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "regression_reference.hpp" -#include "regression_config.hpp" - -#include "net_model.hpp" -#include "segmentation_matcher.hpp" -#include "custom_matcher.hpp" -#include "raw_matcher.hpp" -#include "classification_matcher.hpp" -#include "object_detection_matcher.hpp" -#include "optimized_network_matcher.hpp" - -#include "functional_test_utils/plugin_cache.hpp" - -#ifdef near -#undef near -#endif - - -namespace Regression { -using namespace Matchers; - -/** - * @brief wether to reset plugin after feeding this input, default is false. - */ - -#define afterReset(ACTOR) setCustomInput([&](const Regression::InferenceContext & _) -> \ - Regression::RegressionConfig::InputFetcherResult{return {true, false, false};}) - -#define withCustomInput(ACTOR) setCustomInput([&](const Regression::InferenceContext & _) -> \ - Regression::RegressionConfig::InputFetcherResult{ACTOR; return {};}) - -#define withCustomOutput(ACTOR) setCustomOutput([&](const Regression::InferenceContext & _){ACTOR;}) -#define withCustomModel(ACTOR) setCustomModel([&](const Regression::InferenceContext & _){ACTOR;}) - - -enum EMean { - eNo, - eValues, - eImage -}; - -static std::string format_mean(EMean isMean) { - switch (isMean) { - case eNo:return "_no_mean"; - - case eImage:return "_mf"; - - case eValues:return ""; - } - return nullptr; -} - -inline std::ostream &operator<<(std::ostream &os, EMean mean) { - return os << format_mean(mean); -} - -template -class ModelSelector { - - template - friend class ModelSelector; // every B is a friend of A - - - enum EPrecision { - eq78, efp32, efp16, ei16, ei8 - }; - - enum EGroup { - eNoGroup, eGroup - }; - - - static std::string format_precision(EPrecision precision) { - switch (precision) { - case efp32:return "fp32"; - - case eq78:return "q78"; - - case efp16:return "fp16"; - - case ei16:return "i16"; - - case ei8: return "i8"; - } - return nullptr; - } - - static std::string format_group(EGroup isGroup) { - switch (isGroup) { - case eNoGroup:return ""; - - case eGroup:return "_group"; - } - return nullptr; - } - - friend std::ostream &operator<<(std::ostream &os, EPrecision precision) { - return os << format_precision(precision); - } - - friend std::ostream &operator<<(std::ostream &os, EGroup group) { - return os << format_group(group); - } - - - Model model; - RegressionConfig config; - EMean isMean = eValues; - EPrecision precision = eq78; - EGroup isGroup = eNoGroup; - - private: - std::string prepareModelMatching() { - std::stringstream path_to_input; - path_to_input << TestDataHelpers::get_data_path(); - path_to_input << kPathSeparator - << model.resolution() << kPathSeparator; - for (auto & fileName : config._paths_to_images) { - fileName = path_to_input.str() + fileName; - } - - if (model.folderName().empty() || model.fileName().empty()) { - return ""; - } - ModelsPath path_to_model; - std::stringstream prc; - path_to_model << kPathSeparator - << model.folderName() << kPathSeparator - << model.fileName() << "_" << precision << isMean << isGroup << "." << model.extension(); - - return path_to_model.str(); - } - - ModelSelector() = default; - - std::string getReferenceResultsLabel() { - std::stringstream ss; - for (auto&& v: config.ie_core->GetVersions(config._device_name)) { - const InferenceEngine::Version& version = v.second; - if (nullptr != version.description) { - ss << version.description; - break; - } - } - std::string pluginName = ss.str(); - if (pluginName.empty()) - std::cerr << "getReferenceResultsLabel() failed for device: \"" << config._device_name << "\"" << std::endl; - - return pluginName + "_" + model.folderName() + format_mean(isMean) - + "_" + format_precision(precision) + format_group(isGroup); - } - - bool loadBlobFile(const char* fname, std::vector& outData) - { - if (!fname) - return false; - FILE *f = fopen(fname, "rb"); - if (!f) { - return false; - } - fseek(f, 0, SEEK_END); - int fsize = ftell(f); - fseek(f, 0, SEEK_SET); - outData.resize(fsize); - size_t bytesRead = fread(outData.data(), 1, fsize, f); - if (bytesRead != fsize) { - std::cout << "cannot read file" << std::endl; - return false; - } - fclose(f); - - return true; - } - public : - - explicit ModelSelector(const RegressionConfig& config) : config(config) {} - - template - explicit ModelSelector(T *oldSelector) { - config = oldSelector->config; - } - - ModelSelector &And(const std::string &fileName) { - config._paths_to_images.push_back(fileName); - return *this; - } - - ModelSelector &And(const std::vector &filesNamesVector) { - config._paths_to_images.insert(config._paths_to_images.end(), filesNamesVector.begin(), filesNamesVector.end()); - return *this; - } - - ModelSelector &on(const std::string &fileName) { - config._paths_to_images.push_back(fileName); - return *this; - } - - ModelSelector &print(const std::size_t printNum = 10) { - config.print = true; - config.printNum = printNum; - return *this; - } - - ModelSelector &useExportImport() { - config.useExportImport = true; - return *this; - } - - /// @breif - tile last batch - ModelSelector &onN_infers(int nTimesCopyInputImages) { - if (config._paths_to_images.size() != config.batchSize) { - IE_THROW() << "number of input images:" - << config._paths_to_images.size() << " not equal to batch size: " << config.batchSize; - } - auto first_image = config._paths_to_images.end(); - std::advance(first_image, -config.batchSize); - - std::vector data_for_last_infer(first_image, config._paths_to_images.end()); - - for (;nTimesCopyInputImages > 0; nTimesCopyInputImages--) { - config._paths_to_images.insert(config._paths_to_images.end(), data_for_last_infer.begin(), data_for_last_infer.end()); - } - return *this; - } - /** - * @brief - tile last input image - * @param nTimesCopyLastImagePlusOne = number of times last image will be tiled + 1 - * @deprecated - */ - ModelSelector ×(int nTimesCopyLastImagePlusOne) { - tile(nTimesCopyLastImagePlusOne - 1); - return *this; - } - /** - * @brief - tile last input image - * @param nTimesCopyLastImage = number of times last image will be tiled - * @deprecated - */ - ModelSelector &tile(int nTimesCopyLastImage) { - if (config._paths_to_images.empty()) { - return *this; - } - auto lastImage = config._paths_to_images.back(); - for (;nTimesCopyLastImage > 0; nTimesCopyLastImage--) { - config._paths_to_images.push_back(lastImage); - } - return *this; - } - - ModelSelector &onModel( - std::string _folderName, - std::string _fileName, - std::string _resolutionName) { - model = {_folderName, _fileName, _resolutionName}; - return *this; - } - - ModelSelector &onArkInput() { - model = {model.folderName(), model.fileName(), "ark"}; - return *this; - } - - ModelSelector &onFP32() { - precision = efp32; - config.modelPrecision = Precision::FP32; - return *this; - } - - ModelSelector &onI16() { - precision = ei16; - config.modelPrecision = Precision::I16; - return *this; - } - - ModelSelector &onFP16() { - precision = efp16; - config.modelPrecision = Precision::FP16; - return *this; - } - - ModelSelector &onQ78() { - precision = eq78; - config.modelPrecision = Precision::Q78; - return *this; - } - - ModelSelector& onI8() { - precision = ei8; - config.modelPrecision = Precision::I8; - return *this; - } - - ModelSelector &withInputPrecision(InferenceEngine::Precision p) { - config._inputPrecision = p; - return *this; - } - - ModelSelector &withOutputPrecision(InferenceEngine::Precision p) { - config._outputPrecision = p; - return *this; - } - - ModelSelector &withOutputPrecision(std::map p) { - static_assert(std::is_same::value, "Output precision per blob implemented only in RawMatcher"); - config._outputBlobPrecision = p; - return *this; - } - - template - typename enable_if::value, bool>::type - needInput() const { - return false; - } - - template - typename enable_if::value, bool>::type - needInput() const { - return true; - } - - ModelSelector &withBatch() { - config.batchMode = true; - return *this; - } - - ModelSelector &withBatch(int nBatchSize) { - config.batchSize = nBatchSize; - // assumption made that inputs already gets provided to matcher - if (config._paths_to_images.empty() && needInput()) { - IE_THROW() << "withBatch token should follow after setting up inputs"; - } - if (config._paths_to_images.size() < nBatchSize) { - tile(nBatchSize - config._paths_to_images.size()); - } - - return *this; - } - - ModelSelector &withDynBatch(int nLimit, int nBatchSize) { - config.batchMode = true; - config.useDynamicBatching = true; - config.batchSize = nLimit; - config.dynBatch = nBatchSize; - return *this; - } - - ModelSelector &withAsyncInferRequests(int nRequests) { - config._nrequests = nRequests; - return *this; - } - - ModelSelector &onMultipleNetworks(int nNetworks) { - config._numNetworks = nNetworks; - return *this; - } - - ModelSelector &setMean(EMean mean) { - isMean = mean; - return *this; - } - - ModelSelector &withoutMean() { - isMean = eNo; - return *this; - } - - ModelSelector &withMeanValues() { - isMean = eValues; - return *this; - } - - ModelSelector &withMeanImage() { - isMean = eImage; - return *this; - } - - ModelSelector &withGroup() { - isGroup = eGroup; - return *this; - } - - ModelSelector withTopK(int topKNumbers) { - config.topKNumbers = topKNumbers; - return *this; - } - - ModelSelector &withPluginConfig(const std::map & plugin_config) { - config.plugin_config = plugin_config; - return *this; - } - - ModelSelector &addPluginConfig(const std::map & plugin_config) { - config.plugin_config.insert(plugin_config.begin(), plugin_config.end()); - return *this; - } - - ModelSelector &withPluginConfigOption(std::string key, std::string value) { - config.plugin_config[key] = value; - return *this; - } - - ModelSelector & withImportedExecutableNetworkFrom(std::string location) { - config._path_to_aot_model = location; - return *this; - } - - template - ModelSelector &modifyConfig(const T & modifier) { - modifier(config); - return *this; - } - - ModelSelector & usingAsync() { - config.isAsync = true; - return *this; - } - - ModelSelector &fromLayer(const std::string & name) { - config.outputLayer = name; - return *this; - } - - ModelSelector& doReshape(bool reshape = true) { - config._reshape = reshape; - return *this; - } - - // type define when class in one of building method converted to new one or not -#define CUSTOM_TYPE\ - typename std::conditional::value,\ - ModelSelector&,\ - ModelSelector>::type - - private : - template - typename enable_if::value, CUSTOM_TYPE>::type modify_config(const A& action) { - action(config); - return *this; - } - - template - typename enable_if::value, CUSTOM_TYPE>::type modify_config(const A& action) { - ModelSelector newSelector(this); - action(newSelector.config); - return newSelector; - } - - public: - - template - CUSTOM_TYPE setCustomModel(const T& model_maker) { - return modify_config([&](RegressionConfig & this_config) { - this_config.make_model = model_maker; - }); - } - - template - CUSTOM_TYPE setCustomInput(const T & fetcher) { - return modify_config([&](RegressionConfig & this_config) { - this_config.fetch_input.push_back(fetcher); - }); - } - - template - CUSTOM_TYPE setCustomOutput(const T & fetcher) { - return modify_config([&](RegressionConfig & this_config) { - this_config.fetch_result = fetcher; - }); - } - - template - M equalsTo(const std::initializer_list & rhs) { - config.referenceOutput.insert(config.referenceOutput.end(), rhs.begin(), rhs.end()); - return near(0.0); - } - - template - M near(double nearValue, const TBlob & rhs) { - config.nearValue = nearValue; - for (const auto & v : rhs) { - config.referenceOutput.push_back(v); - } - config._path_to_models = prepareModelMatching(); - return M(config); - } - - M to(Blob::Ptr rhs) { - config.outputBlob = rhs; - config._path_to_models = prepareModelMatching(); - return M(config); - } - - - template - M near(double nearValue, const initializer_list> & rhs) { - config.nearValue = nearValue; - - for (auto && frame : rhs) { - for (auto && data : frame) { - config.referenceOutput.push_back(data); - } - } - config._path_to_models = prepareModelMatching(); - return M(config); - } - - template - M near_avg(double nearAvgValue, const TBlob & rhs) { - config.nearAvgValue = nearAvgValue; - return near(0.0, rhs); - } - - M near(double nearValue, double meanRelativeError = 0, double maxRelativeError = 0) { - config.nearValue = nearValue; - config.meanRelativeError = meanRelativeError; - config.maxRelativeError = maxRelativeError; - config._path_to_models = prepareModelMatching(); - return M(config); - } - - void equalToReferenceWithDelta(double nearValue) { - config.nearValue = nearValue; - config._path_to_models = prepareModelMatching(); - M(config).to(getReferenceResultsLabel()); - } - - template - M equalToReference(const TBlob & rhs) { - for (const auto & v : rhs) { - config.referenceOutput.push_back(v); - } - config._path_to_models = prepareModelMatching(); - return M(config, true); - } - - // place holder to run the matcher without providing any reference - void possible() { - config._path_to_models = prepareModelMatching(); - auto tmp = M(config); - ASSERT_NO_FATAL_FAILURE(tmp.match()); - } -}; - -/** - * @class PluginVersion - * @brief A PluginVersion class stores plugin version and initialization status - */ -struct PluginVersion : public InferenceEngine::Version { - bool initialized = false; - - explicit PluginVersion(const InferenceEngine::Version *ver) { - if (nullptr == ver) { - return; - } - InferenceEngine::Version::operator=(*ver); - initialized = true; - } - - operator bool() const noexcept { - return initialized; - } -}; - -class Builder { -private: - std::shared_ptr ie; - RegressionConfig config; - -public: - Builder(std::shared_ptr _ie) : ie(_ie) { - config.ie_core = ie; - -#ifndef NDEBUG - auto devices = ie->GetAvailableDevices(); - std::cout << "Available devices (" << devices.size() << "):" << std::endl; - for (auto&& d : devices) { - std::cout << "Device: " << d << std::endl; - for (auto&& v : ie->GetVersions(d)) - std::cout << "\t" << v.first << " : " << PluginVersion(&v.second) << std::endl; - } -#endif - } - - Builder & usingDevice(const std::string & device_name) { - config._device_name = device_name; - return *this; - } - - Builder& setPerfInfo(std::map& map) { - config.perfInfoPtr = ↦ - config.plugin_config[CONFIG_KEY(PERF_COUNT)] = CONFIG_VALUE(YES); - return *this; - } - - Builder& setDeviceMapping(const std::map &deviceMapping) { - config.deviceMapping = deviceMapping; - return *this; - } - - ModelSelector classificationResults() { - return ModelSelector(config); - } - - ModelSelector classificationResultsFor(const std::vector & input) { - return ModelSelector(config).And(input); - } - - ModelSelector dumpedOptimizedNetwork() { - return ModelSelector(config); - } - - ModelSelector dumpOptimizedNetworkTo(const std::string & file) { - config._path_to_aot_model = file; - return ModelSelector(config); - } - - ModelSelector classificationResultsFor(const std::string &input = { }) { - auto selector = ModelSelector(config); - if (!input.empty()) { - selector.And(input); - } - return selector; - } - - ModelSelector segmentationResultsFor(const std::string &fileName) { - return ModelSelector(config).And(fileName); - } - ModelSelector rawResultsFor(const std::string &fileName) { - return ModelSelector(config).And(fileName); - } - ModelSelector objectDetectionResultsFor(const std::string &fileName) { - return ModelSelector(config).And(fileName); - } - ModelSelector objectDetectionResults() { - return ModelSelector(config); - } - ModelSelector objectDetectionResultsFor(const vector &filesNamesVector) { - return ModelSelector(config).And(filesNamesVector); - } -}; - -class RegressionTests : public TestsCommon { -public: - // to force overload - virtual std::string getDeviceName() const = 0; - - Builder please() { - std::shared_ptr ie = PluginCache::get().ie(getDeviceName()); - Builder b(ie); - b.usingDevice(getDeviceName()); - return b; - } -}; - -} - -#define assertThat() SCOPED_TRACE("");please() -#define saveAfterInfer() SCOPED_TRACE("");please() diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/segmentation_matcher.hpp b/inference-engine/tests_deprecated/functional/ie_tests/include/segmentation_matcher.hpp deleted file mode 100644 index fdc86455ede..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/include/segmentation_matcher.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include - -#include -#include -#include "base_matcher.hpp" - -/** - * @class Color - * @brief A Color class stores channels of a given color - */ -class Color { -private: - unsigned char _r; - unsigned char _g; - unsigned char _b; - -public: - /** - * A default constructor. - * @param r - value for red channel - * @param g - value for green channel - * @param b - value for blue channel - */ - Color(unsigned char r, - unsigned char g, - unsigned char b) : _r(r), _g(g), _b(b) {} - - inline unsigned char red() { - return _r; - } - - inline unsigned char blue() { - return _b; - } - - inline unsigned char green() { - return _g; - } -}; - -namespace Regression { namespace Matchers { - -class SegmentationMatcher : public BaseMatcher { - private: - InferenceEngine::TBlob::Ptr output; - std::vector> outArray; - size_t C = -1; - - public: - SegmentationMatcher (const RegressionConfig & config) - : BaseMatcher(config) { - } - - virtual void match(); - - static float compareOutputBmp(std::vector> data, size_t classesNum, const std::string& inFileName); - - void checkResult(std::string imageFileName); - - SegmentationMatcher& to(std::string imageFileName) { - match(); - checkResult(imageFileName); - return *this; - } -}; - -} } // namespace matchers diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/base_matcher.cpp b/inference-engine/tests_deprecated/functional/ie_tests/src/base_matcher.cpp deleted file mode 100644 index 9be0afecb4c..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/src/base_matcher.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "base_matcher.hpp" -#include -#include - -namespace Regression { namespace Matchers { - -using namespace InferenceEngine; - -void loadImage(const std::string &imageFilename, InferenceEngine::Blob::Ptr &blob, bool bgr, int batchNumber) { - TensorDesc tensDesc = blob->getTensorDesc(); - if (tensDesc.getPrecision() != InferenceEngine::Precision::FP16 - && tensDesc.getPrecision() != InferenceEngine::Precision::FP32 - && tensDesc.getPrecision()!= InferenceEngine::Precision::U8 - && tensDesc.getPrecision()!= InferenceEngine::Precision::I16) { - IE_THROW() << "loadImage error: Input must have FP16, FP32 or U8 precision"; - } - - if (tensDesc.getLayout() != NHWC && tensDesc.getLayout() != NCHW) { - IE_THROW() << "loadImage error: Input must have NHWC or NHWC layout"; - } - - FormatReader::ReaderPtr reader(imageFilename.c_str()); - if (reader.get() == nullptr) { - IE_THROW() << "loadImage error: image " << imageFilename << " cannot be read!"; - } - - size_t w = tensDesc.getDims()[3]; - size_t h = tensDesc.getDims()[2]; - if (reader->width() != w || reader->height() != h) { - IE_THROW() << "loadImage error: Input sizes mismatch, got " << reader->width() << "x" << reader->height() - << " expecting " << w << "x" << h; - } - - auto numBlobChannels = tensDesc.getDims()[1]; - size_t numImageChannels = reader->size() / (reader->width() * reader->height()); - if (numBlobChannels != numImageChannels && numBlobChannels != 1) { - IE_THROW() << "loadImage error: Input channels mismatch: image channels " << numImageChannels << ", " - << "network channels " << numBlobChannels << ", expecting count of image channels are equal " - << "to count if network channels or count of network channels are equal to 1"; - } - - auto nPixels = w * h; - uint8_t *BGR8 = reader->getData().get(); - for (unsigned int i = 0; i < nPixels; i++) { - for (unsigned int j = 0; j < numBlobChannels; j++) { - uint8_t val = bgr ? BGR8[i * numImageChannels + j] : BGR8[i * numBlobChannels + (numBlobChannels - j - 1)]; - size_t idx = tensDesc.getLayout() == NHWC ? (i * numBlobChannels + j) : (j * nPixels + i) - + nPixels * numBlobChannels * batchNumber; - auto buf = blob->buffer(); - switch (blob->getTensorDesc().getPrecision()) { - case Precision::U8: - { - auto inputDataPtr = buf.as(); - inputDataPtr[idx] = val; - break; - } - case Precision::I16: - { - auto *inputDataPtr = buf.as(); - inputDataPtr[idx] = val; - break; - } - case Precision::FP16: - { - ie_fp16 *inputDataPtr = buf.as(); - inputDataPtr[idx] = InferenceEngine::PrecisionUtils::f32tof16(static_cast(val)); - break; - } - case Precision::FP32: - { - auto inputDataPtr = buf.as(); - inputDataPtr[idx] = static_cast(val); - break; - } - default: - IE_THROW() << "Unsupported precision!"; - } - } - } -} - -void BaseMatcher::checkImgNumber(int dynBatch) { - InferenceEngine::Core ieCore; - CNNNetwork net = ieCore.ReadNetwork(config._path_to_models); - auto numInputs = net.getInputsInfo().size(); - - int batch = dynBatch > 0 ? dynBatch : config.batchSize; - - if ((numInputs * batch) > config._paths_to_images.size()) { - - auto readImagesSize = config._paths_to_images.size(); - size_t diff = (numInputs * batch) / readImagesSize; - - for (size_t i = 1; i < diff; i++) { - for (size_t j = 0; j < readImagesSize; j++) { - config._paths_to_images.push_back(config._paths_to_images[j]); - } - } - if (readImagesSize * diff != (numInputs * batch)) { - for (size_t j = 0; j < (numInputs * batch) - readImagesSize * diff; j++) { - config._paths_to_images.push_back(config._paths_to_images.at(j)); - } - } - } else if ((numInputs * batch) < config._paths_to_images.size()) { - while (config._paths_to_images.size() != batch * numInputs) { - auto name = config._paths_to_images.back(); - std::cout << "[WARNING]: Image " << name << " skipped!" << std::endl; - config._paths_to_images.pop_back(); - } - } -} - -} // namepspace Matchers -} // namespace Regression diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/classification_matcher.cpp b/inference-engine/tests_deprecated/functional/ie_tests/src/classification_matcher.cpp deleted file mode 100644 index 7147b1b0879..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/src/classification_matcher.cpp +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "classification_matcher.hpp" -#include -#include -#include - -using namespace Regression ; -using namespace Regression :: Matchers ; - -ClassificationMatcher::ClassificationMatcher(RegressionConfig &config) - : BaseMatcher(config) { - // Get file names for files with weights and labels - std::string binFileName = testing::FileUtils::fileNameNoExt(config._path_to_models) + ".bin"; - - auto cnnNetwork = config.ie_core->ReadNetwork(config._path_to_models, binFileName); - - std::string labelFileName = testing::FileUtils::fileNameNoExt(config._path_to_models) + ".labels"; - - // Try to read labels file - readLabels(labelFileName); - - if (config._reshape) { - auto inputShapes = cnnNetwork.getInputShapes(); - inputShapes.begin()->second[0] = config.batchSize; - - cnnNetwork.reshape(inputShapes); - } else if (config.batchSize != 1) { - cnnNetwork.setBatchSize(config.batchSize); - } - - _inputsInfo = cnnNetwork.getInputsInfo(); - _outputsInfo = cnnNetwork.getOutputsInfo(); - for (auto &info : _inputsInfo) { - if (config._inputPrecision != InferenceEngine::Precision::UNSPECIFIED) { - info.second->setPrecision(config._inputPrecision); - } - } - - for (auto &info : _outputsInfo) { - if (config._outputPrecision != Precision::UNSPECIFIED) { - info.second->setPrecision(config._outputPrecision); - } else { - info.second->setPrecision(config.modelPrecision); - } - } - - if (config.useDynamicBatching) { - config.plugin_config[PluginConfigParams::KEY_DYN_BATCH_ENABLED] = PluginConfigParams::YES; - cnnNetwork.setBatchSize(config.batchSize); - } - - for (int i=0; i < config._numNetworks; i++) { - auto loadedExecutableNetwork = config.ie_core->LoadNetwork(cnnNetwork, config._device_name, config.plugin_config); - InferenceEngine::ExecutableNetwork executableNetwork; - if (config.useExportImport) { - std::stringstream stream; - loadedExecutableNetwork.Export(stream); - executableNetwork = config.ie_core->ImportNetwork(stream); - } else { - executableNetwork = loadedExecutableNetwork; - } - _executableNetworks.push_back(executableNetwork); - } - - top = (-1 == config.topKNumbers) ? 5 : config.topKNumbers; -} - -void ClassificationMatcher::to(const std::vector &expected) { - checkResultNumber = 0; - match(std::min(top, expected.size())); - checkResult(checkResultNumber, expected); - checkResultNumber++; -} - -void ClassificationMatcher::to(std::string modelType) { - auto batchSize = config.batchSize; - - if (config.useDynamicBatching) { - batchSize = config.dynBatch; - } - - checkImgNumber(batchSize); - ASSERT_NO_FATAL_FAILURE(match(10)); // This method produces top-10 reference results. - for (size_t i = 0; i < config._paths_to_images.size(); i++) { - const size_t last_slash_idx = config._paths_to_images[i].find_last_of(kPathSeparator); - if (std::string::npos != last_slash_idx) { - config._paths_to_images[i].erase(0, last_slash_idx + 1); - } - if (Regression::Reference::values.find(modelType + "_" + config._paths_to_images[i]) == - Regression::Reference::values.end()) { - FAIL() << "Reference result for " << modelType + "_" + config._paths_to_images[i] << " cannot be found"; - } - ASSERT_NO_FATAL_FAILURE(checkResult(i, Regression::Reference::values[modelType + "_" + config._paths_to_images[i]])); - } - checkResultNumber++; -} - - -void ClassificationMatcher::readLabels(std::string labelFilePath) { - std::fstream fs(labelFilePath, std::ios_base::in); - if (fs.is_open()) { - std::string line; - while (getline(fs, line)) { - config.labels.push_back(TestsCommon::trim(line)); - } - } else { - IE_THROW() << "cannot open label file: " << labelFilePath; - - } -} - -int ClassificationMatcher::getIndexByLabel(const std::string &label) { - auto result = std::find(begin(config.labels), end(config.labels), label); - if (result == config.labels.end()) { - IE_THROW() << "cannot locate index for label : " << label; - } - return static_cast(std::distance(begin(config.labels), result)); -} - -std::string ClassificationMatcher::getLabel(unsigned int index) { - if (config.labels.empty()) { - return "label #" + std::to_string(index); - } - if (index >= config.labels.size()) { - IE_THROW() << "index out of labels file: " << index; - } - - return config.labels[index]; -} - -void ClassificationMatcher::checkResult(size_t checkNumber, - const std::vector &expected) { - if (checkNumber >= _results.size()) { - FAIL() << "Expected number of results(" << checkNumber << ") is more than real number of results: " - << _results.size(); - } - auto result = _results.at(checkNumber); - - std::map expected_map; - int expectedSize = expected.size(); - int resultSize = result.size(); - - if (config.topKNumbers != -1) { - expectedSize = config.topKNumbers; - resultSize = config.topKNumbers; - } - - for (int i = 0; i < expectedSize; ++i) { - expected_map[expected[i].getLabel()] = expected[i].getProbability(); - } - - for (int i = 0; i < resultSize; ++i) { - if (expected_map.count(result[i].getLabel())) { - ASSERT_NEAR(result[i].getProbability(), expected_map[result[i].getLabel()], config.nearValue) - << "Failed for label \"" << result[i].getLabel() << "\" index " << i; - expected_map.erase(result[i].getLabel()); - } else { - // Label which not in expected list can be below last expected element - ASSERT_LE(result[i].getProbability(), expected.back().getProbability() + config.nearValue) - << "Label \"" << result[i].getLabel() << "\" not found or cannot be in expected list"; - } - } - - if (expected_map.size() != 0) { - for (auto & elem: expected_map) { - std::cout << "Label \"" << elem.first << "\" with probability=" - << elem.second << " not found in result list" << std::endl; - } - FAIL(); - } -} - -void ClassificationMatcher::match(size_t top) { - for (int i = 0; i != _executableNetworks.size(); i++) { - match_n(top, i); - } -} - -namespace { - -template -inline void TopResults(unsigned int n, TBlob& input, std::vector& output) { - SizeVector dims = input.getTensorDesc().getDims(); - size_t input_rank = dims.size(); - if (!input_rank || !dims[0]) IE_THROW() << "Input blob has incorrect dimensions!"; - size_t batchSize = dims[0]; - std::vector indexes(input.size() / batchSize); - - n = static_cast(std::min((size_t)n, input.size())); - - output.resize(n * batchSize); - - for (size_t i = 0; i < batchSize; i++) { - size_t offset = i * (input.size() / batchSize); - T* batchData = input.data(); - batchData += offset; - - std::iota(std::begin(indexes), std::end(indexes), 0); - std::partial_sort(std::begin(indexes), std::begin(indexes) + n, std::end(indexes), - [&batchData](unsigned l, unsigned r) { - return batchData[l] > batchData[r]; - }); - for (unsigned j = 0; j < n; j++) { - output.at(i * n + j) = indexes.at(j); - } - } -} - -} - -void ClassificationMatcher::match_n(size_t top, int index) { - try { - auto inferRequest = _executableNetworks[index].CreateInferRequest(); - std::string prevImageName = ""; - - auto batchSize = config.batchSize; - - if (config.useDynamicBatching) { - batchSize = config.dynBatch; - inferRequest.SetBatch(batchSize); - } - - if (config._paths_to_images.size() % batchSize != 0) { - IE_THROW() << "Can not process all input images("<< config._paths_to_images.size() - <<") using given batch size of " << batchSize; - } - // loading images in batches - for (int i = 0; i < config._paths_to_images.size(); i += batchSize) { - - // has same image names - bool areImagesSame = false; - if (i > 0) { - areImagesSame = true; - for (int j = i;j != i + batchSize; j++) { - if (config._paths_to_images[j] != config._paths_to_images[j - batchSize]) { - areImagesSame = false; - break; - } - } - } - if (!areImagesSame) { - for (int j = 0; j != batchSize; j++) { - const auto & imageName = config._paths_to_images[i + j]; - - auto inputBlob = inferRequest.GetBlob(_inputsInfo.begin()->first.c_str()); - loadImage(imageName, inputBlob, true, j); - } - } - - inferRequest.Infer(); - - auto outputBlobPtr = inferRequest.GetBlob(_outputsInfo.begin()->first.c_str()); - - InferenceEngine::TBlob::Ptr outputFP32; - if (outputBlobPtr->getTensorDesc().getPrecision() == InferenceEngine::Precision::FP16) { - TensorDesc desc = { InferenceEngine::Precision::FP32, outputBlobPtr->getTensorDesc().getDims(), - outputBlobPtr->getTensorDesc().getLayout() }; - outputFP32 = make_shared_blob(desc); - outputFP32->allocate(); - PrecisionUtils::f16tof32Arrays(outputFP32->buffer().as(), outputBlobPtr->cbuffer().as(), outputBlobPtr->size()); - } else if (outputBlobPtr->getTensorDesc().getPrecision() == InferenceEngine::Precision::FP32) { - outputFP32 = dynamic_pointer_cast>(outputBlobPtr); - } else { - IE_THROW() << "Unsupported output format for test. Supported FP16, FP32"; - } - - vector topClassesIndexes; - TopResults(top, *outputFP32, topClassesIndexes); - std::vector probabilities(outputFP32->buffer().as(), - outputFP32->buffer().as() + outputFP32->size()); - - saveResults(topClassesIndexes, probabilities, top); - } - } catch (InferenceEngine::Exception &e) { - FAIL() << e.what(); - } catch (std::exception &e) { - FAIL() << e.what(); - } -} - -void ClassificationMatcher::saveResults(const std::vector &topIndexes, const std::vector &probs, size_t top) { - - for(auto idx = topIndexes.begin(); idx != topIndexes.end();) { - std::vector topResults; - for (int i = 0; i != top; i++) { - Reference::LabelProbability labelProb(*idx, probs[*idx], getLabel(*idx)); - std::cout << "index=" << labelProb.getLabelIndex() << ", probability=" << labelProb.getProbability() - << ", class=" << labelProb.getLabel() << "\n"; - topResults.push_back(labelProb); - idx++; - } - _results.push_back(topResults); - } -} diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/custom_matcher.cpp b/inference-engine/tests_deprecated/functional/ie_tests/src/custom_matcher.cpp deleted file mode 100644 index 6ce4b3d0f4e..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/src/custom_matcher.cpp +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include "custom_matcher.hpp" - -using namespace InferenceEngine; - -InferenceEngine::ExecutableNetwork Regression::Matchers::CustomMatcher::createExecutableNetworkFromAOT() { - ExecutableNetwork executableApi; - try { - ctx.setFileNames(config._paths_to_images); - ctx.setModelPrecision(config.modelPrecision); - - executableApi = config.ie_core->ImportNetwork(config._path_to_aot_model, config._device_name, config.plugin_config); - } - catch (std::exception &e) { - GTEST_MESSAGE_(e.what(), ::testing::TestPartResult::kFatalFailure); - } - - return executableApi; - -} - -InferenceEngine::ExecutableNetwork Regression::Matchers::CustomMatcher::createExecutableNetworkFromIR(){ - ExecutableNetwork executableApi; - try { - ctx.setFileNames(config._paths_to_images); - ctx.setModelPrecision(config.modelPrecision); - - if (config.make_model) { - ctx.setModelPath(config._path_to_models); - config.make_model(ctx); - } - - std::string binFileName = testing::FileUtils::fileNameNoExt(config._path_to_models) + ".bin"; - network = config.ie_core->ReadNetwork(config._path_to_models, binFileName); - - // Change batch size if it is not equal 1 - auto inputs = network.getInputsInfo(); - - if (config._inputPrecision) { - for (auto && input : inputs) { - input.second->setPrecision(config._inputPrecision); - // NC is a proper layout for 2d blob if different is not specified, like CN - auto layout = input.second->getTensorDesc().getDims().size() == 4 ? NCHW : NC; - input.second->getInputData()->setLayout(layout); - } - } - - //TODO: why this need - if (inputs.begin()->second->getTensorDesc().getDims().at(0) != 1) { - std::cerr << "[WARNING]: Batch size will be equal to 1." << std::endl; - network.setBatchSize(1); - } - - if (config.batchSize != 1) { - network.setBatchSize(config.batchSize); - } - - if (!config.outputLayer.empty()) { - network.addOutput(config.outputLayer); - } - - if (config.useDynamicBatching) { - config.plugin_config[PluginConfigParams::KEY_DYN_BATCH_ENABLED] = PluginConfigParams::YES; - } - - auto outInfo = network.getOutputsInfo(); - - auto loadedExecutableNetwork = config.ie_core->LoadNetwork(network, config._device_name, config.plugin_config); - if (config.useExportImport) { - std::stringstream stream; - loadedExecutableNetwork.Export(stream); - executableApi = config.ie_core->ImportNetwork(stream); - } else { - executableApi = loadedExecutableNetwork; - } - - } - catch (std::exception &e) { - GTEST_MESSAGE_(e.what(), ::testing::TestPartResult::kFatalFailure); - } - - return executableApi; -} - -void Regression::Matchers::CustomMatcher::matchCustom() { - try { - ExecutableNetwork executableApi; - std::vector inferRequests; - ConstInputsDataMap constInputs; - ConstOutputsDataMap constOutInfo; - ResponseDesc dsc; - StatusCode sts = OK; - - if (!config._path_to_aot_model.empty()) { - ASSERT_NO_FATAL_FAILURE(executableApi = createExecutableNetworkFromAOT()); - } else { - ASSERT_NO_FATAL_FAILURE(executableApi = createExecutableNetworkFromIR()); - } - - if (executableApi) { - for (int i=0; i != config._nrequests; i++ ) { - inferRequests.push_back(executableApi.CreateInferRequest()); - } - } - - if (config.useDynamicBatching) { - for (auto && req : inferRequests) { - req.SetBatch(config.dynBatch); - } - } - - auto make_unified_endpoints = [&] () { - if (executableApi) { - return std::make_pair(executableApi.GetInputsInfo(), executableApi.GetOutputsInfo()); - } - auto inputs2 = network.getInputsInfo(); - ConstInputsDataMap constInputs2; - for (const auto & input : inputs2) { - constInputs2[input.first] = input.second; - } - auto output2 = network.getOutputsInfo(); - ConstOutputsDataMap constOutInfo2; - for (const auto & output : output2) { - constOutInfo2[output.first] = output.second; - } - return std::make_pair(constInputs2, constOutInfo2); - }; - - auto endpoints = make_unified_endpoints(); - - for (auto && fetch_input : config.fetch_input) { - // each fetcher can be used multiple times - for (;;) { - // load new input - reset if necessary - decltype(fetch_input(ctx)) fetchResult; - - int requestProcessed = 0; - for (int i = 0; i != config._nrequests; i++) { - int inputId = 0; - for (auto input : endpoints.first) { - InferenceEngine::Blob::Ptr inputBlb; - inputBlb = inferRequests[i].GetBlob(input.first); - ctx.setInput(input.second->name(), inputBlb); - ctx.setInputIdx(inputId); - decltype(fetch_input(ctx)) fetchResultForInput; - ASSERT_NO_FATAL_FAILURE(fetchResultForInput = fetch_input(ctx)); - if (inputId != 0) { - ASSERT_EQ(fetchResult.fetched, fetchResultForInput.fetched); - ASSERT_EQ(fetchResult.fetchMore, fetchResultForInput.fetchMore); - ASSERT_EQ(fetchResult.frameNumber, fetchResultForInput.frameNumber); - ASSERT_EQ(fetchResult.reset, fetchResultForInput.reset); - } else { - fetchResult = fetchResultForInput; - } - inputId++; - } - - if (fetchResult.fetched) { - // number of requests to infer in parallel - requestProcessed++; - // increasing frame number this however might be done in input fetcher if CTX passed by non const reference - // value used in read_next_.. fetchers family - ctx.setFrameNumber(ctx.getFrameNumber() + 1); - } - // cannot spawn more requests due to reset - if (fetchResult.reset) { - break; - } - // end of stream - if (!fetchResult.fetchMore) { - break; - } - } - - if (fetchResult.fetched) { - // Infer model - if (requestProcessed == 1) { - inferRequests.front().Infer(); - sts = OK; - } else { - for (int i = 0; i != requestProcessed; i++) { - inferRequests[i].StartAsync(); - } - for (int i = 0; i != requestProcessed; i++) { - inferRequests[i].Wait(InferRequest::RESULT_READY); - } - sts = OK; - } - - if (!fetchResult.hasResult) { - continue; - } - - // for infer request case will copy resulted blob - for (int i = 0; i != requestProcessed;i++) { - auto &outputs = ctx.newOutputs(); - for (auto output : endpoints.second) { - auto tblob = dynamic_pointer_cast>(inferRequests[i].GetBlob(output.second->getName())); - outputs[output.second->getName()] = make_shared_blob(*tblob); - } - } - } - - IE_SUPPRESS_DEPRECATED_START - if (fetchResult.reset) { - auto states = executableApi.QueryState(); - ASSERT_FALSE(states.empty()); - for(auto& state : states) { - state.Reset(); - } - // also store reset indicator for comparison routine - auto &outputs = ctx.newOutputs(); - outputs["reset"] = nullptr; - //continue; - } - IE_SUPPRESS_DEPRECATED_END - - //FAIL()<<"stop after one frame"; - - // Check errors - if (sts == GENERAL_ERROR) { - IE_THROW() << "Scoring failed! Critical error: " << dsc.msg; - } else if (sts == NOT_IMPLEMENTED) { - IE_THROW() << "Scoring failed! Input data is incorrect and not supported!"; - } else if (sts == NETWORK_NOT_LOADED) { - IE_THROW() << "Scoring failed! " << dsc.msg; - } - if (!fetchResult.fetchMore) break; - } - } - } - catch (std::exception &e) { - FAIL() << e.what(); - } -} - -void Regression::Matchers::CustomMatcher::checkResult() { - bool cmpNear = !isApproximatelyEqual(config.nearValue, 0.0); - bool cmpNearAvg = !isApproximatelyEqual(config.nearAvgValue, 0.0); - bool isSaveOutput = !!config.outputBlob; - - /** - * In case where external comparison is used - */ - if (isSaveOutput) { - if (!config.fetch_result) { - // calculating all outputs size - SizeVector dimsMerged; - for(auto && output : ctx.allOutputs()) { - auto outputBlobIt = config.outputLayer.empty() ? output.begin() : output.find(config.outputLayer); - auto outBlob = outputBlobIt->second; - - if (dimsMerged.empty()) { - dimsMerged = outBlob->getTensorDesc().getDims(); - } else { - ASSERT_EQ(dimsMerged.size(), outBlob->getTensorDesc().getDims().size()); - int added = 0; - std::transform(begin(dimsMerged), - end(dimsMerged), - begin(dimsMerged = outBlob->getTensorDesc().getDims()), - begin(dimsMerged), - [&added](size_t l, size_t r) { - added += l != r; - return added ? l + r : l; - }); - ASSERT_LE(added,1); - - if (added == 0 && !dimsMerged.empty()) { - dimsMerged.back() += outBlob->getTensorDesc().getDims().back(); - } - } - } - - config.outputBlob->deallocate(); - config.outputBlob->getTensorDesc() = TensorDesc(config.outputBlob->getTensorDesc().getPrecision(), - dimsMerged, - TensorDesc::getLayoutByDims(dimsMerged)); - config.outputBlob->allocate(); - float *buff = config.outputBlob->buffer(); - - // copying all output frames into allocated blob - for(auto && output : ctx.allOutputs()) { - - auto outputBlobIt = config.outputLayer.empty() ? output.begin() : output.find(config.outputLayer); - auto outBlob = dynamic_pointer_cast>(outputBlobIt->second); - - for (auto value : *outBlob) { - *(buff++) = value; - } - } - - } else { - auto outBlob = dynamic_pointer_cast>(config.fetch_result(ctx)); - - config.outputBlob->deallocate(); - config.outputBlob->getTensorDesc() = TensorDesc(outBlob->getTensorDesc().getPrecision(), - outBlob->getTensorDesc().getDims(), - TensorDesc::getLayoutByDims(outBlob->getTensorDesc().getDims())); - config.outputBlob->allocate(); - float *buff = config.outputBlob->buffer(); - - int i = 0; - for (auto value : *outBlob) { - buff[i++] = value; - } - } - return; - } - - if (cmpNear || cmpNearAvg) { - int idx = 0; - float avgDiff = 0.0f; - float maxDiff = 0.0f; - float maxAverageDiff = 0.0f; - float rms = 0.0f; - int nFrame = -1; - float avgFrames = 0.0f; - - if (!config.fetch_result) { - decltype(ctx.allOutputs().begin()) output; - for(;;) { - avgFrames++; - if (nFrame == -1) { - output = ctx.allOutputs().begin(); - nFrame = 0; - } else { - nFrame++; - ++output; - } - if (output == ctx.allOutputs().end()) { - break; - } - auto outputBlobIt = config.outputLayer.empty() ? output->begin() : output->find(config.outputLayer); - auto outBlob = dynamic_pointer_cast>(outputBlobIt->second); - - // fo reset case we are storing fake blob pointer - if (outBlob == nullptr) { - avgDiff = 0.0; - rms = 0.0; - nFrame--; - avgFrames = 0.0; - continue; - } - float rmsp = 0.0; - float avgDiffp = 0.0; - ASSERT_LE(outBlob->size(), config.referenceOutput.size()); - for (auto value : *outBlob) { - if (cmpNear) { - ASSERT_NEAR(value, config.referenceOutput[idx], config.nearValue) << " at " << idx; - } - auto diff = abs(value - config.referenceOutput[idx]); - avgDiffp += diff; - rmsp += diff*diff; - maxDiff = std::max(maxDiff, diff); - idx++; - } - - rmsp = sqrt(rmsp / outBlob->size()); - rms += rmsp; - avgDiffp /= outBlob->size(); - avgDiff += avgDiffp; - maxAverageDiff = std::max(maxAverageDiff, avgDiff / avgFrames); - - //TODO: add test_log parse from command line -// #define TEST_LOG -#ifdef TEST_LOG - auto threshold_similarity_max = config.nearValue - maxDiff; - auto threshold_similarity_avg = config.nearAvgValue - avgDiff / avgFrames; - - cout << "Frame # " << nFrame << "\n"; - cout << "MaxDiff : " << maxDiff << " (" - << std::fixed << std::setprecision(5) << threshold_similarity_max <<")" << "\n"; - cout << "RMSE : " << rmsp << "\n"; - cout << "AvgDiff/f : " << avgDiffp << "\n"; - cout << "MaxAvgDiff: " << maxAverageDiff - << std::fixed << std::setprecision(5) << " (" << threshold_similarity_avg <<")" << std::endl; -#endif - - if (cmpNearAvg) { - ASSERT_NEAR(avgDiff / avgFrames, 0, config.nearAvgValue); - } - } - } else { - auto ptr = dynamic_pointer_cast>(config.fetch_result(ctx)); - - for (auto value : *ptr) { - if (cmpNear) { - ASSERT_NEAR(value, config.referenceOutput[idx], config.nearValue) << " at " << idx; - } - if (cmpNearAvg) { - avgDiff += abs(value - config.referenceOutput[idx]); - } - idx++; - } - if (cmpNearAvg) { - avgDiff /= ptr->size(); - } - } - } else { - // for small expectations lets use string as a compare buddy - stringstream ss, ssr; - - if (!config.fetch_result) { - for (auto output : ctx.outputs()) { - auto outBlob = dynamic_pointer_cast>(output.second); - for (auto value : *outBlob) { - ss << setprecision(precision) << fixed << (float)value << "."; - } - } - } else { - auto ptr = dynamic_pointer_cast>(config.fetch_result(ctx)); - - for (auto value : *ptr) { - ss << setprecision(precision) << fixed << (float)value << "."; - } - } - - for (auto value : config.referenceOutput) { - ssr << setprecision(precision) << fixed << (float)value << "."; - } - - ASSERT_STREQ(ssr.str().c_str(), ss.str().c_str()); - } -} diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/net_model.cpp b/inference-engine/tests_deprecated/functional/ie_tests/src/net_model.cpp deleted file mode 100644 index edea2ae0384..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/src/net_model.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "net_model.hpp" - -//------------------------------------------------------------------------------ -// Implementation of methods of class Model -//------------------------------------------------------------------------------ - -Model::Model(const std::string &folderName, - const std::string &fileName, - const std::string &resolution, - const std::string & extension) : - folderName_(folderName), - fileName_(fileName), - resolutionName_(resolution), - extensionName_(extension) { -}; diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/object_detection_matcher.cpp b/inference-engine/tests_deprecated/functional/ie_tests/src/object_detection_matcher.cpp deleted file mode 100644 index f1c7ab8046d..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/src/object_detection_matcher.cpp +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "object_detection_matcher.hpp" -#include - -#include - -using namespace Regression::Matchers; - -namespace Regression { -namespace Matchers { - -using DetectedObject = ObjectDetectionMatcher::DetectedObject; -using ImageDescription = ObjectDetectionMatcher::ImageDescription; -using namespace InferenceEngine; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ObjectDetectionMatcher::DetectedObject ////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -ObjectDetectionMatcher::DetectedObject::DetectedObject(int objectType, - float xmin, - float ymin, - float xmax, - float ymax, - float prob, - int) - : objectType(objectType), xmin(xmin), xmax(xmax), ymin(ymin), ymax(ymax), prob(prob) { -} - -ObjectDetectionMatcher::DetectedObject::DetectedObject(const DetectedObject &other) { - this->objectType = other.objectType; - this->xmin = other.xmin; - this->xmax = other.xmax; - this->ymin = other.ymin; - this->ymax = other.ymax; - this->prob = other.prob; -} - -float ObjectDetectionMatcher::DetectedObject::ioU(const DetectedObject &detected_object_1_, - const DetectedObject &detected_object_2_) { - // Add small space to eliminate empty squares - float epsilon = 1e-3; - - DetectedObject detectedObject1(detected_object_1_.objectType, - detected_object_1_.xmin - epsilon, - detected_object_1_.ymin - epsilon, - detected_object_1_.xmax + epsilon, - detected_object_1_.ymax + epsilon, detected_object_1_.prob); - DetectedObject detectedObject2(detected_object_2_.objectType, - detected_object_2_.xmin - epsilon, - detected_object_2_.ymin - epsilon, - detected_object_2_.xmax + epsilon, - detected_object_2_.ymax + epsilon, detected_object_2_.prob); - - if (detectedObject1.objectType != detectedObject2.objectType) { - // objects are different, so the result is 0 - return 0.0f; - } - - if (detectedObject1.xmax < detectedObject1.xmin) return 0.0; - if (detectedObject1.ymax < detectedObject1.ymin) return 0.0; - if (detectedObject2.xmax < detectedObject2.xmin) return 0.0; - if (detectedObject2.ymax < detectedObject2.ymin) return 0.0; - - float xmin = (std::max)(detectedObject1.xmin, detectedObject2.xmin); - float ymin = (std::max)(detectedObject1.ymin, detectedObject2.ymin); - float xmax = (std::min)(detectedObject1.xmax, detectedObject2.xmax); - float ymax = (std::min)(detectedObject1.ymax, detectedObject2.ymax); - // intersection - float intr; - - if ((xmax >= xmin) && (ymax >= ymin)) { - intr = (xmax - xmin) * (ymax - ymin); - } else { - intr = 0.0f; - } - - // union - float square1 = (detectedObject1.xmax - detectedObject1.xmin) * (detectedObject1.ymax - detectedObject1.ymin); - float square2 = (detectedObject2.xmax - detectedObject2.xmin) * (detectedObject2.ymax - detectedObject2.ymin); - - float unn = square1 + square2 - intr; - - return float(intr) / unn; -} - -void ObjectDetectionMatcher::DetectedObject::printObj() { - printf("[%p] objectType=%d, xmin=%f, xmax=%f, ymin=%f, ymax=%f, prob=%f\n", - this, - objectType, - xmin, - xmax, - ymin, - ymax, - prob); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ObjectDetectionMatcher::ImageDescription //////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -ObjectDetectionMatcher::ImageDescription::ImageDescription(bool check_probs) : - check_probs_(check_probs) { -} - -ObjectDetectionMatcher::ImageDescription::ImageDescription(const std::list &alist, bool check_probs) - : alist(alist), check_probs_(check_probs) { -} - -ObjectDetectionMatcher::ImageDescription::ImageDescription(const ImageDescription &obj) : - check_probs_(obj.checkProbs()) { - this->alist = obj.alist; -} - -float ObjectDetectionMatcher::ImageDescription::ioUMultiple(const ImageDescription &detected_objects, - const ImageDescription &desired_objects) { - - const ImageDescription *detectedObjectsSmall, *detectedObjectsBig; - bool check_probs = desired_objects.checkProbs(); - - if (detected_objects.alist.size() < desired_objects.alist.size()) { - detectedObjectsSmall = &detected_objects; - detectedObjectsBig = &desired_objects; - } else { - detectedObjectsSmall = &desired_objects; - detectedObjectsBig = &detected_objects; - } - - std::list doS = detectedObjectsSmall->alist; - std::list doB = detectedObjectsBig->alist; - - float fullScore = 0.0f; - while (doS.size() > 0) { - float score = 0.0f; - std::list::iterator bestJ = doB.end(); - for (auto j = doB.begin(); j != doB.end(); j++) { - float curscore = DetectedObject::ioU(*doS.begin(), *j); - if (score < curscore) { - score = curscore; - bestJ = j; - } - } - - float coeff = 1.0; - if (check_probs) { - if (bestJ != doB.end()) { - DetectedObject test = *bestJ; - DetectedObject test1 = *doS.begin(); - float min = std::min((*bestJ).prob, (*doS.begin()).prob); - float max = std::max((*bestJ).prob, (*doS.begin()).prob); - - coeff = min / max; - } - } - - doS.pop_front(); - if (bestJ != doB.end()) doB.erase(bestJ); - fullScore += coeff * score; - } - fullScore /= detectedObjectsBig->alist.size(); - - return fullScore; -} - -void ObjectDetectionMatcher::ImageDescription::addDetectedObject(const DetectedObject &detected_obj) { - alist.push_back(detected_obj); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ObjectDetectionMatcher::ObjectDetectionMatcher ////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -ObjectDetectionMatcher::ObjectDetectionMatcher(const RegressionConfig &config) - : BaseMatcher(config) { -} - -void ObjectDetectionMatcher::match(const ScoreFunction& score_function) { - // Read network - string binFileName = testing::FileUtils::fileNameNoExt(config._path_to_models) + ".bin"; - auto cnnNetwork = config.ie_core->ReadNetwork(config._path_to_models, binFileName); - - if (config._reshape) { - auto inputShapes = cnnNetwork.getInputShapes(); - for (auto & shape : inputShapes) { - shape.second[0] = config.batchSize; - } - - cnnNetwork.reshape(inputShapes); - } else if (config.batchSize != 1) { - cnnNetwork.setBatchSize(config.batchSize); - } - - res_desc_ = score_function(cnnNetwork); - - if (res_desc_.size() != config.batchSize) { - FAIL() << "[ERROR]: Result batch size is not equal to initial."; - } -} - -void ObjectDetectionMatcher::checkResult(const std::vector &desired) { - if ((desired.size() < config.batchSize) || (res_desc_.size() != config.batchSize)) { - FAIL() << "[ERROR]: Number of ImageDescription objects less then batch size or result batch size is not equal to initial.\n" - << "Batch size: " << config.batchSize << "; Expected outputs number: " << desired.size() - << "; Result number: " << res_desc_.size(); - } - string sError; - for (int i = 0; i < config.batchSize; i++) { - double iou = ImageDescription::ioUMultiple(*res_desc_[i], desired[i]); - double minimalScore = 1.0 - config.nearValue; - if (iou < minimalScore) { - sError += "[ERROR]: Batch #" + std::to_string(i) + ". Similarity is too low: " + std::to_string(iou) - + ". Expected " + std::to_string(minimalScore) + "\n"; - } else { - std::cout << "Batch #" << i << ". Similarity " << iou << " is above the expected value: " << minimalScore - << std::endl; - } - } - - if (!sError.empty()) { - FAIL() << sError; - } -} - -void ObjectDetectionMatcher::to(const ImageDescription &desired, const std::shared_ptr& adapter) { - std::vector desired_vector = {desired}; - ASSERT_NO_FATAL_FAILURE(to(desired_vector, adapter)); -} - -void ObjectDetectionMatcher::to(const std::vector &desired, - const std::shared_ptr& adapter) { - to(desired, [&](CNNNetwork & network) -> ImageDescriptionPtrVect { - return adapter->score(network, - config.ie_core, - config._device_name, - config.plugin_config, - config._paths_to_images, - config._reshape, - config.useExportImport); - }); -} - -void ObjectDetectionMatcher::to(const ImageDescription &desired, const NetworkAdapter& adapter) { - std::vector desired_vector = {desired}; - ASSERT_NO_FATAL_FAILURE(to(desired_vector, adapter)); -} - -void ObjectDetectionMatcher::to(const std::vector &desired, - const NetworkAdapter& adapter) { - to(desired, [&](CNNNetwork& network) -> ImageDescriptionPtrVect { - return adapter.score(network, - config.ie_core, - config._device_name, - config.plugin_config, - config._paths_to_images, - config._reshape); - }); -} - -void ObjectDetectionMatcher::to(const std::vector &desired, const ScoreFunction& score_function) { - // ASSERT_NO_FATAL_FAILURE(checkImgNumber()); - ASSERT_NO_FATAL_FAILURE(match(score_function)); - if (desired.size() < config.batchSize) { - std::cout << "Number of ImageDescription objects less then batch size" << std::endl; - std::vector newRef; - for (int i = 0; i < config.batchSize; i++) { - newRef.push_back(desired[0]); - } - ASSERT_NO_FATAL_FAILURE(checkResult(newRef)); - } else { - ASSERT_NO_FATAL_FAILURE(checkResult(desired)); - } -} - -} // namespace matchers -} // namespace regression \ No newline at end of file diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/optimized_network_matcher.cpp b/inference-engine/tests_deprecated/functional/ie_tests/src/optimized_network_matcher.cpp deleted file mode 100644 index 63bce010583..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/src/optimized_network_matcher.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include -#include "optimized_network_matcher.hpp" - -using namespace InferenceEngine; -using namespace InferenceEngine::PluginConfigParams; - - -void Regression :: Matchers :: OptimizedNetworkMatcher :: to(std::string path_to_reference_dump) { - ModelsPath path_to_firmware; - path_to_firmware << kPathSeparator << config._firmware << kPathSeparator; - - auto compact_token = config.compactMode ? "_compact" : ""; - - this->path_to_reference_dump = path_to_firmware + path_to_reference_dump + compact_token + "_firmware.bin"; -} - -void Regression :: Matchers :: OptimizedNetworkMatcher :: matchCustom () { - ASSERT_NO_FATAL_FAILURE(createExecutableNetworkFromIR()); - firmware = readDumpFromFile(config._tmp_firmware); - ASSERT_NE(firmware.size(), 0); -} - -std::vector Regression :: Matchers :: OptimizedNetworkMatcher :: readDumpFromFile(std::string path) { - std::ifstream file(path, std::ios::binary | std::ios::ate); - std::streamsize size = file.tellg(); - if (size <=0) { - return std::vector(); - } - file.seekg(0, std::ios::beg); - - std::vector buffer(size); - file.read((char*)buffer.data(), size); - - return buffer; -} - -void Regression :: Matchers :: OptimizedNetworkMatcher :: checkResult() { - auto refFirmware = readDumpFromFile(path_to_reference_dump); - - ASSERT_EQ(refFirmware.size(), firmware.size()) << "Reference: " << path_to_reference_dump; - - for (int i = 0; i < refFirmware.size(); ++i) { - ASSERT_EQ(refFirmware[i], firmware[i]) << "firmware mismatch at: " << i << " byte"; - } -} - -//////////////////////////// - -void Regression :: Matchers :: OptimizedNetworkDumper::dump() { - ExecutableNetwork executableApi; - ASSERT_NO_FATAL_FAILURE(executableApi = createExecutableNetworkFromIR()); - try { - executableApi.Export(config._path_to_aot_model); - } - catch (const std::exception &e) { - FAIL() << e.what(); - } - -} diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/raw_matcher.cpp b/inference-engine/tests_deprecated/functional/ie_tests/src/raw_matcher.cpp deleted file mode 100644 index 59c65031d29..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/src/raw_matcher.cpp +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include "raw_matcher.hpp" -#include - -namespace Regression { -namespace Matchers { - -void RawMatcher::match() { - try { - // Read network - std::string binFileName = testing::FileUtils::fileNameNoExt(config._path_to_models) + ".bin"; - std::cout << config._path_to_models << std::endl; - auto cnnNetwork = config.ie_core->ReadNetwork(config._path_to_models, binFileName); - - InferenceEngine::InputsDataMap networkInputs; - networkInputs = cnnNetwork.getInputsInfo(); - if (networkInputs.size() == 0) { - IE_THROW() << "No inputs detected."; - } - - if (config._paths_to_images.size() % ( config.batchSize * networkInputs.size()) != 0) { - std::cerr << "[WARNING]: Can not process all input images("<< config._paths_to_images.size() - <<") using given batch size of " << config.batchSize << ". Batch size will be equal 1." << std::endl; - config.batchSize = 1; - } - - InferenceEngine::DataPtr inputData = cnnNetwork.getInputsInfo().begin()->second->getInputData(); - InferenceEngine::SizeVector inputDims = inputData->getTensorDesc().getDims(); - - if (config._reshape) { - auto inputShapes = cnnNetwork.getInputShapes(); - inputShapes.begin()->second[0] = config.batchSize; - - cnnNetwork.reshape(inputShapes); - } else if (config.batchSize != 1) { - cnnNetwork.setBatchSize(config.batchSize); - } - - // TODO(amalyshe) quick dirty solution which might not cover all topologies, - // but covers only networks having one input passing to one layer - CNNLayerPtr layer; - for (auto input : networkInputs) { - InputInfo::Ptr q = input.second; - if (config._inputPrecision) q->setPrecision(config._inputPrecision); - DataPtr p = q->getInputData(); - IE_SUPPRESS_DEPRECATED_START - layer = getInputTo(p).begin()->second; - IE_SUPPRESS_DEPRECATED_END - } - - { - // Set output precision - InferenceEngine::OutputsDataMap out; - out = cnnNetwork.getOutputsInfo(); - for (auto &&item : out) { - Blob::Ptr output; - auto outputName = item.first; - auto& outBlob = item.second; - if (config._outputPrecision) outBlob->setPrecision(config._outputPrecision); - if (config._outputBlobPrecision.count(outputName)) outBlob->setPrecision(config._outputBlobPrecision[outputName]); - } - } - - if (!config.deviceMapping.empty()) { - IE_SUPPRESS_DEPRECATED_START - CNNNetDFS(layer, [&](const CNNLayerPtr &layer) { - auto it = config.deviceMapping.find(layer->name); - if (it != config.deviceMapping.end()) { - layer->affinity = it->second; - } else { - layer->affinity = "CPU"; - } - }); - IE_SUPPRESS_DEPRECATED_END - } - - // Read image - std::vector> imagesData; - unsigned int actualNetSize = 0; - for (auto & imageName : config._paths_to_images) { - FormatReader::ReaderPtr reader(imageName.c_str()); - if (reader.get() == nullptr) { - IE_THROW() << "[ERROR]: Image " + imageName + " cannot be read!"; - } - actualNetSize += reader->size(); - // Store image data - - size_t width = 0, height = 0; - SizeVector dims = inputData->getTensorDesc().getDims(); - if (dims.size() == 3) { - height = dims.at(1); - width = dims.at(2); - } else if (dims.size() == 4) { - height = dims.at(2); - width = dims.at(3); - } else if (dims.size() == 5) { - height = dims.at(3); - width = dims.at(4); - } else { - IE_THROW() << inputData->getName() << " has unsupported layout " << inputData->getTensorDesc().getLayout(); - } - - std::shared_ptr data(reader->getData(width, height)); - if (data.get() != nullptr) { - imagesData.push_back(data); - } else { - IE_THROW() << "Invalid image '" << imageName << "'"; - } - } - - auto out2 = cnnNetwork.getOutputsInfo(); - for (auto &&item : out2) { - if (config._outputPrecision) item.second->setPrecision(config._outputPrecision); - if (config._outputBlobPrecision.count(item.first)) { - item.second->setPrecision(config._outputBlobPrecision[item.first]); - } - } - - auto loadedExecutableNetwork = config.ie_core->LoadNetwork(cnnNetwork, config._device_name, config.plugin_config); - InferenceEngine::ExecutableNetwork executableNetwork; - if (config.useExportImport) { - std::stringstream stream; - loadedExecutableNetwork.Export(stream); - executableNetwork = config.ie_core->ImportNetwork(stream); - } else { - executableNetwork = loadedExecutableNetwork; - } - auto inferRequest = executableNetwork.CreateInferRequest(); - - InferenceEngine::BlobMap inputBlobs; - - auto allocateBlob = [](const InferenceEngine::TensorDesc& desc) { - InferenceEngine::Blob::Ptr blob; - switch (desc.getPrecision()) { - case InferenceEngine::Precision::FP32 : - blob = InferenceEngine::make_shared_blob(desc); - break; - case InferenceEngine::Precision::FP16 : - case InferenceEngine::Precision::Q78 : - case InferenceEngine::Precision::I16 : - blob = InferenceEngine::make_shared_blob(desc); - break; - case InferenceEngine::Precision::U8 : - blob = InferenceEngine::make_shared_blob(desc); - break; - default: - IE_THROW() << "Unsupported blob precision: " << desc.getPrecision(); - } - blob->allocate(); - - return blob; - }; - - for(auto&& inputInfo : cnnNetwork.getInputsInfo()) { - std::string inputName = inputInfo.first; - - if (!inferRequest) { - // Allocate blobs - inputBlobs[inputName] = allocateBlob(inputInfo.second->getTensorDesc()); - } else { - inputBlobs[inputName] = inferRequest.GetBlob(inputName); - } - } - - { - InferenceEngine::OutputsDataMap out; - out = cnnNetwork.getOutputsInfo(); - for (auto &&item : out) { - Blob::Ptr output; - auto outputName = item.first; - if (!inferRequest) { - output = allocateBlob(item.second->getTensorDesc()); - } else { - // TODO(amalyshe): we need to return GetBlob eventually after the fix bug in mkldnnplugin - output = inferRequest.GetBlob(outputName); - // output = allocateBlob(item.second->getTensorDesc()); - // inferRequest.SetBlob(outputName, output); - } - outputBlobs[outputName] = output; - } - } - - // loading images in batches - for (int i = 0; i < config._paths_to_images.size(); i += config.batchSize * inputBlobs.size()) { - int k = 0; - for(auto&& input: inputBlobs) { - for (int j = 0; j != config.batchSize; j++) { - const auto & imageName = config._paths_to_images[i + j + k]; - loadImage(imageName, input.second, true, j); - } - k++; - } - - if (config.isAsync) { - inferRequest.StartAsync(); - inferRequest.Wait(InferRequest::WaitMode::RESULT_READY); - } else { - inferRequest.Infer(); - } - - // Get performance info - if (config.perfInfoPtr != nullptr) { - *config.perfInfoPtr = inferRequest.GetPerformanceCounts(); - } - } - } catch (Exception &e) { - FAIL() << e.what(); - } - catch (std::exception &e) { - FAIL() << e.what(); - } -} - -void RawMatcher::checkResult(const std::map> &allExpected) { - auto prepareResults = [&](const Blob::Ptr& output) { - std::vector tmp_buffer; - - if (output->getTensorDesc().getPrecision() == InferenceEngine::Precision::FP16) { - tmp_buffer.resize(output->size(), 0.f); - PrecisionUtils::f16tof32Arrays(tmp_buffer.data(), - output->buffer().as(), - output->size()); - } else { - assert(output->getTensorDesc().getPrecision() == InferenceEngine::Precision::FP32); - tmp_buffer.resize(output->size(), 0.f); - std::copy_n(output->buffer().as(), output->size(), tmp_buffer.begin()); - } - - return tmp_buffer; - }; - if(config.print) { - std::cout << "{"; - for(auto&& out : outputBlobs) { - Blob::Ptr& output = out.second; - auto results = prepareResults(output); - std::cout << "{{\"" << out.first <<"\", {\n"; - for(std::size_t i = 0; i < output->size(); i += (output->size() + config.printNum - 1)/ config.printNum) { - std::cout << "{" << i <<", "<< results[i] << "},\n"; - } - std::cout << "}}},\n"; - } - std::cout << "};" << std::endl; - } else { - std::stringstream strm; - auto generateInfo = [&](const std::vector& results, const std::map& expected) { - double meanRelative = 0; - double maxAbsolute = 0; - double maxRelative = 0; - strm << std::endl << std::setw(15) << "Position" << std::setw(15) << - "Expected" << std::setw(15) << - "Actual" << std::setw(15) << - "Absolute" << std::setw(15) << - "Relative,%" << std::endl; - for (auto e : expected) { - double absolute = fabs(e.second - results[e.first]); - double relative = fabs(e.second - results[e.first]) / fabs(e.second); - - strm << std::setw(15) << e.first - << std::setw(15) << std::setprecision(6) << e.second - << std::setw(15) << std::setprecision(6) << results[e.first] - << std::setw(15) << std::setprecision(6) << absolute - << std::setw(15) << std::setprecision(6) << relative*100 << std::endl; - meanRelative += relative; - maxAbsolute = std::max(maxAbsolute, absolute); - maxRelative = std::max(maxRelative, relative); - } - strm << "Max Absolute = " << maxAbsolute - << " Mean Relative = " << meanRelative*100/expected.size() - << " Max Relative = " << maxRelative*100 << '\n'; - }; - - if(0 != config.nearValue) { - for(auto expectedPair : allExpected) { - Blob::Ptr output = outputBlobs[expectedPair.first]; - if (!output) { - FAIL() << "Was not able to find expected output " << expectedPair.first; - } - - auto results = prepareResults(output); - - const std::map &expected = expectedPair.second; - - for (auto e : expected) { - if (fabs(e.second - results[e.first]) > config.nearValue) { - strm << "In blob " << expectedPair.first - << " element at " << e.first << " index expected to be " << e.second << " but in fact it is " - << results[e.first] << - " Delta = " << (fabs(e.second - results[e.first])); - generateInfo(results, expected); - FAIL() << strm.str(); - } - } - } - } - if(0 != config.meanRelativeError) { - for(auto expectedPair : allExpected) { - Blob::Ptr output = outputBlobs[expectedPair.first]; - if (!output) { - FAIL() << "Was not able to find expected output " << expectedPair.first; - } - auto results = prepareResults(output); - - std::map& expected = expectedPair.second; - - double meanRelative = 0; - for (auto e : expected) { - double eps = fabs(e.second - results[e.first]) / fabs(e.second); - meanRelative += eps; - } - meanRelative /= expected.size(); - meanRelative *= 100; - - if (meanRelative > config.meanRelativeError) { - strm << "In blob " << expectedPair.first - << " Mean Relative Error = " << meanRelative - << " Expected Mean Relative Error = " << config.meanRelativeError; - generateInfo(results, expected); - FAIL() << strm.str(); - } - } - } - if(0 != config.maxRelativeError) { - for(auto expectedPair : allExpected) { - Blob::Ptr output = outputBlobs[expectedPair.first]; - if (!output) { - FAIL() << "Was not able to find expected output " << expectedPair.first; - } - auto results = prepareResults(output); - - std::map& expected = expectedPair.second; - - double maxRelative = 0; - std::size_t maxPos = 0; - for (auto e : expected) { - double eps = fabs(e.second - results[e.first]) / fabs(e.second); - if(eps > maxRelative) { - maxRelative = eps; - maxPos = e.first; - } - } - maxRelative *= 100; - - if (maxRelative > config.maxRelativeError) { - strm << "In blob " << expectedPair.first << " element at " << maxPos << " index" - << " expected to be " << expected[maxPos] << " but in fact it is " << results[maxPos] - << " Max Relative Error = " << maxRelative - << " Expected Max Relative Error = " << config.maxRelativeError; - generateInfo(results, expected); - FAIL() << strm.str(); - } - } - } - } -} - -} -} // namespace matchers diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/segmentation_matcher.cpp b/inference-engine/tests_deprecated/functional/ie_tests/src/segmentation_matcher.cpp deleted file mode 100644 index 45afd5a2880..00000000000 --- a/inference-engine/tests_deprecated/functional/ie_tests/src/segmentation_matcher.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include - -#include "segmentation_matcher.hpp" - -static std::vector> blobToImageOutputArray(InferenceEngine::TBlob::Ptr output, - size_t *pWidth, size_t *pHeight, - size_t *pChannels) { - std::vector> outArray; - size_t W = 0, C = 0, H = 0; - - auto outputDims = output->getTensorDesc().getDims(); - if (outputDims.size() == 3) { - C = outputDims.at(0); - H = outputDims.at(1); - W = outputDims.at(2); - } else if (outputDims.size() == 4) { - C = outputDims.at(1); - H = outputDims.at(2); - W = outputDims.at(3); - } else if (outputDims.size() == 5) { - C = outputDims.at(1); - H = outputDims.at(3); - W = outputDims.at(4); - } else { - IE_THROW() << "Output blob has unsupported layout " << output->getTensorDesc().getLayout(); - } - - // Get classes - const float *outData = output->data(); - for (unsigned h = 0; h < H; h++) { - std::vector row; - for (unsigned w = 0; w < W; w++) { - float max_value = outData[h * W + w]; - size_t index = 0; - for (size_t c = 1; c < C; c++) { - size_t dataIndex = c * H * W + h * W + w; - if (outData[dataIndex] > max_value) { - index = c; - max_value = outData[dataIndex]; - } - } - row.push_back(index); - } - outArray.push_back(row); - } - - if (pWidth != nullptr) *pWidth = W; - if (pHeight != nullptr) *pHeight = H; - if (pChannels != nullptr) *pChannels = C; - - return outArray; -} - -namespace Regression { namespace Matchers { - -void SegmentationMatcher::match() { - // Read network - std::string binFileName = testing::FileUtils::fileNameNoExt(config._path_to_models) + ".bin"; - auto network = config.ie_core->ReadNetwork(config._path_to_models, binFileName); - - // Change batch size if it is not equal 1 - InferenceEngine::InputsDataMap inputs; - inputs = network.getInputsInfo(); - ASSERT_EQ(inputs.size() ,1); - InferenceEngine::InputInfo::Ptr ii = inputs.begin()->second; - - InferenceEngine::SizeVector inputDims = ii->getTensorDesc().getDims(); - if (inputDims.at(0) != 1) { - std::cerr << "[WARNING]: Batch size will be equal 1." << std::endl; - network.setBatchSize(1); - inputDims = ii->getTensorDesc().getDims(); - } - - InferenceEngine::OutputsDataMap outInfo; - outInfo = network.getOutputsInfo(); - ASSERT_EQ(outInfo.size(), 1); - ASSERT_NE(outInfo.begin()->second, nullptr); - - InferenceEngine::SizeVector outputDims = outInfo.begin()->second->getDims(); - - if (outputDims.size() != 4) { - IE_THROW() << "Incorrect output dimensions for Deconvolution model"; - } - - // Read image - FormatReader::ReaderPtr reader(config._paths_to_images[0].c_str()); - if (reader.get() == nullptr) { - IE_THROW() << "[ERROR]: Image " << config._paths_to_images[0] << " cannot be read!"; - } - - int inputNetworkSize = static_cast(std::accumulate( - inputDims.begin(), inputDims.end(), (size_t)1, std::multiplies())); - - if (reader->size() != inputNetworkSize) { - IE_THROW() << "[ERROR]: Input sizes mismatch, got " << reader->size() << " bytes, expecting " - << inputNetworkSize; - } - - // Allocate blobs - InferenceEngine::Blob::Ptr input; - switch (inputs.begin()->second->getPrecision()) { - case InferenceEngine::Precision::FP32 : - input = InferenceEngine::make_shared_blob({ InferenceEngine::Precision::FP32, inputDims, NCHW }); - break; - case InferenceEngine::Precision::Q78 : - case InferenceEngine::Precision::I16 : - input = InferenceEngine::make_shared_blob({ InferenceEngine::Precision::I16, inputDims, NCHW }); - break; - case InferenceEngine::Precision::U8 : - input = InferenceEngine::make_shared_blob({ InferenceEngine::Precision::U8, inputDims, NCHW }); - break; - default: - IE_THROW() << "Unsupported network precision: " << inputs.begin()->second->getPrecision(); - } - input->allocate(); - - output = InferenceEngine::make_shared_blob(outInfo.begin()->second->getTensorDesc()); - output->allocate(); - - // Load image to blob - ConvertImageToInput(reader->getData().get(), reader->size(), *input); - - auto loadedExecutableNetwork = config.ie_core->LoadNetwork(network, config._device_name, config.plugin_config); - InferenceEngine::ExecutableNetwork executableNetwork; - if (config.useExportImport) { - std::stringstream stream; - loadedExecutableNetwork.Export(stream); - executableNetwork = config.ie_core->ImportNetwork(stream); - } else { - executableNetwork = loadedExecutableNetwork; - } - - auto inferRequest = executableNetwork.CreateInferRequest(); - inferRequest.SetBlob(inputs.begin()->first.c_str(), input); - inferRequest.SetBlob(outInfo.begin()->first.c_str(), output); - - // Infer model - inferRequest.Infer(); - - // Convert output data and save it to image - outArray = blobToImageOutputArray(output, nullptr, nullptr, &C); -} - -float SegmentationMatcher::compareOutputBmp(std::vector> data, size_t classesNum, const std::string& inFileName) { - unsigned int seed = (unsigned int)time(NULL); - std::vector colors = { - {128, 64, 128}, - {232, 35, 244}, - {70, 70, 70}, - {156, 102, 102}, - {153, 153, 190}, - {153, 153, 153}, - {30, 170, 250}, - {0, 220, 220}, - {35, 142, 107}, - {152, 251, 152}, - {180, 130, 70}, - {60, 20, 220}, - {0, 0, 255}, - {142, 0, 0}, - {70, 0, 0}, - {100, 60, 0}, - {90, 0, 0}, - {230, 0, 0}, - {32, 11, 119}, - {0, 74, 111}, - {81, 0, 81} - }; - while (classesNum > colors.size()) { - static std::mt19937 rng(seed); - std::uniform_int_distribution dist(0, 255); - Color color(dist(rng), dist(rng), dist(rng)); - colors.push_back(color); - } - - - FormatReader::ReaderPtr rd(inFileName.c_str()); - if (rd.get() == nullptr) { - IE_THROW() << "[ERROR]: Image " << inFileName << " cannot be read!"; - } - - auto height = data.size(); - auto width = data.at(0).size(); - - if (rd.get()->width() != width || rd.get()->height() != height) { - return 0.0; - } - - float rate = 0.0; - - unsigned char* pixels = rd.get()->getData().get(); - - for (size_t y = 0; y < height; y++) { - for (size_t x = 0; x < width; x++) { - unsigned char pixel[3]; - size_t index = data.at(y).at(x); - pixel[0] = colors.at(index).red(); - pixel[1] = colors.at(index).green(); - pixel[2] = colors.at(index).blue(); - - unsigned char pixelR[3]; - pixelR[0] = pixels[(y*width + x)*3 + 0]; - pixelR[1] = pixels[(y*width + x)*3 + 1]; - pixelR[2] = pixels[(y*width + x)*3 + 2]; - - if (pixel[0] == pixelR[0] && - pixel[1] == pixelR[1] && - pixel[2] == pixelR[2]) { - - rate ++; - } - } - } - - rate /= (width * height); - return rate; -} - -void SegmentationMatcher::checkResult(std::string imageFileName) { - std::ifstream inFile; - - float rate = compareOutputBmp(outArray, C, TestDataHelpers::get_data_path() + "/test_results/" + imageFileName/*ifs*/); - - float dist = 1.0f - rate; - if (dist > config.nearValue) { - FAIL() << "Comparison distance " << dist << " is greater than " << config.nearValue; - } else { - std::cout << "Comparison distance " << dist << " is smaller than " << config.nearValue << std::endl; - } -} - -} } // namespace matchers diff --git a/inference-engine/tests_deprecated/functional/mkldnn/CMakeLists.txt b/inference-engine/tests_deprecated/functional/mkldnn/CMakeLists.txt index b812637b656..9ef991ffee3 100644 --- a/inference-engine/tests_deprecated/functional/mkldnn/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/mkldnn/CMakeLists.txt @@ -2,55 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 # -set(TARGET_NAME MklDnnFunctionalTests) +add_executable(MklDnnFunctionalTests dummy.cpp) -file(GLOB MKL_DNN_TEST_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/config_param_test/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/extensions_tests/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/network_tests/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/regression_tests/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instance/common_single_layer_tests/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instance/graph_tools/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instance/inference_engine_regression_tests/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instance/input_tests/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instance/io_blob_tests/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instance/lstm/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/single_layer_tests/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/snippet_test/*.cpp - ) - -list(APPEND MKL_DNN_LIBS - IESharedTests - ${Boost_REGEX_LIBRARY}) - -list(APPEND TEST_SRC ${MKL_DNN_TEST_SOURCES}) -list(APPEND LIBRARIES ${MKL_DNN_LIBS}) - -list(APPEND DEPENDENCIES - MKLDNNPlugin) - -source_group("src" FILES ${TEST_SRC}) -source_group("include" FILES ${TEST_INCLUDE}) - -add_executable(${TARGET_NAME} - ${TEST_SRC} - ${REGRESSION_TESTS} - ${TEST_INCLUDE}) - -target_compile_definitions(${TARGET_NAME} - PUBLIC ${ARGV} - DATA_PATH=\"${DATA_PATH}\" - MODELS_PATH=\"${MODELS_PATH}\" PARENT_SCOPE) - -target_include_directories(${TARGET_NAME} PRIVATE - ${IE_MAIN_SOURCE_DIR}/src/mkldnn_plugin) - -target_link_libraries(${TARGET_NAME} PRIVATE ${LIBRARIES}) - -set_ie_threading_interface_for(${TARGET_NAME}) - -add_dependencies(${TARGET_NAME} ${DEPENDENCIES}) - -add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME}) -set_property(TEST ${TARGET_NAME} PROPERTY LABELS CPU) +target_link_libraries(MklDnnFunctionalTests PRIVATE gtest_main) diff --git a/inference-engine/tests_deprecated/functional/mkldnn/dummy.cpp b/inference-engine/tests_deprecated/functional/mkldnn/dummy.cpp index ffe853f7697..ace1c25a6d1 100644 --- a/inference-engine/tests_deprecated/functional/mkldnn/dummy.cpp +++ b/inference-engine/tests_deprecated/functional/mkldnn/dummy.cpp @@ -1,4 +1,3 @@ // Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // - diff --git a/inference-engine/tests_deprecated/functional/shared_tests/CMakeLists.txt b/inference-engine/tests_deprecated/functional/shared_tests/CMakeLists.txt index f31d579ba85..a5ec4ed85ab 100644 --- a/inference-engine/tests_deprecated/functional/shared_tests/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/shared_tests/CMakeLists.txt @@ -8,8 +8,9 @@ disable_deprecated_warnings() list(APPEND SHARED_LIBRARIES ${NGRAPH_LIBRARIES} - ie_tests + commonTestUtils ngraphFunctions + ieTestHelpers ) file(GLOB SHARED_TESTS_SRC @@ -28,11 +29,6 @@ ie_faster_build(${TARGET_NAME} PCH PRIVATE "precomp.hpp" ) -if(ENABLE_MKL_DNN) - add_dependencies(${TARGET_NAME} MKLDNNPlugin) - target_compile_definitions(${TARGET_NAME} PUBLIC ENABLE_MKL_DNN) -endif() - # Find OpenCV components if exist find_package(OpenCV COMPONENTS core imgproc QUIET) if(OpenCV_FOUND) @@ -44,11 +40,9 @@ endif() target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/io_blob_tests ${CMAKE_CURRENT_SOURCE_DIR}/input_tests - ${CMAKE_CURRENT_SOURCE_DIR}/inference_engine_regression_tests ${CMAKE_CURRENT_SOURCE_DIR}/lstm ${CMAKE_CURRENT_SOURCE_DIR}/common_single_layer_tests ${CMAKE_CURRENT_SOURCE_DIR}/single_layer_tests - ${CMAKE_CURRENT_SOURCE_DIR}/graph_tools $ ) diff --git a/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/pool_ref.hpp b/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/pool_ref.hpp index 6584b08cbe0..c2cab4f96a7 100644 --- a/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/pool_ref.hpp +++ b/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/pool_ref.hpp @@ -4,8 +4,9 @@ #pragma once +#include #include -#include +#include #include #include "common_test_utils/common_layers_params.hpp" diff --git a/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/single_layer_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/single_layer_tests.hpp index 92976e9cbc1..6cc9b0abc6c 100644 --- a/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/single_layer_tests.hpp +++ b/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/single_layer_tests.hpp @@ -15,7 +15,9 @@ #include "deconv_ref.hpp" #include "def_conv_ref.hpp" #include "pool_ref.hpp" +#include "single_layer_common.hpp" #include "common_test_utils/common_layers_params.hpp" +#include using namespace InferenceEngine; diff --git a/inference-engine/tests_deprecated/functional/shared_tests/graph_tools/graph_tools_functional_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/graph_tools/graph_tools_functional_tests.hpp deleted file mode 100644 index 5ce1b544c59..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/graph_tools/graph_tools_functional_tests.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include -#include - -using namespace testing; -using namespace InferenceEngine::details; -using namespace InferenceEngine; -using namespace std; - -class GraphToolsFncTest : public ::testing::Test { -public: - template - static void checkSort(const T &sorted) { - for (int i = 0; i < sorted.size(); i++) { - //check that all input already visited: - for (auto &inputs : sorted[i]->insData) { - auto inputName = getCreatorLayer(inputs.lock()).lock()->name; - - bool bFound = false; - for (int j = 0; j < i; j++) { - if (sorted[j]->name == inputName) { - bFound = true; - break; - } - } - ASSERT_TRUE(bFound) << "order is not correct, layer " << sorted[i]->name << " has missed input: " - << inputName; - } - } - } -}; diff --git a/inference-engine/tests_deprecated/functional/shared_tests/inference_engine_regression_tests/common_dyn_batch_regression.hpp b/inference-engine/tests_deprecated/functional/shared_tests/inference_engine_regression_tests/common_dyn_batch_regression.hpp deleted file mode 100644 index c7c0d361b4e..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/inference_engine_regression_tests/common_dyn_batch_regression.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include - -using namespace ::testing; -using namespace InferenceEngine; - -class CommonDynBatchFuncTestParams { -public: - std::string deviceName; - double nearValue; - int batch_limit; - int cur_batch; - - CommonDynBatchFuncTestParams(const std::string &_deviceName, - int blimit, - int batch, - double _nearValue = 0.01f) : - deviceName(_deviceName), - batch_limit(blimit), - cur_batch(batch), - nearValue(_nearValue) {} -}; - -template -class TestNoRegressionDynBatch : public Regression::RegressionTests, - public WithParamInterface { - void SetUp() override { -// PluginCache::; - } - - std::string getDeviceName() const override { - return GetParam().deviceName; - } - -public: - int get_batch_limit() { - return GetParam().batch_limit; - } - - int get_cur_batch() { - return GetParam().cur_batch; - } -}; - -using TestNoRegressionDynBatchFP32 = TestNoRegressionDynBatch; - -TEST_P(TestNoRegressionDynBatchFP32, dynBatch) { - int bl = get_batch_limit(); - int bsz = get_cur_batch(); - auto fnPtr = ngraph::builder::subgraph::makeSingleConv({static_cast(bl), 3, 24, 24}); - - CNNNetwork net(fnPtr); - auto ieCore = PluginCache::get().ie(); - InferenceEngine::ExecutableNetwork exeNet = ieCore->LoadNetwork(net, GetParam().deviceName, - {{PluginConfigParams::KEY_DYN_BATCH_ENABLED, - PluginConfigParams::YES}}); - InferenceEngine::InferRequest inferRequest = exeNet.CreateInferRequest(); - - auto blob = FuncTestUtils::createAndFillBlob(net.getInputsInfo().begin()->second->getTensorDesc()); - - inferRequest.SetBatch(bsz); - inferRequest.SetBlob(net.getInputsInfo().begin()->first, blob); - inferRequest.Infer(); - auto *outRawData = inferRequest.GetBlob(net.getOutputsInfo().begin()->first)->cbuffer().as(); - const auto blobSize = blob->byteSize(); - const auto inBlobBuf = blob->cbuffer().as(); - std::vector inData(inBlobBuf, inBlobBuf + blobSize); - auto refOutData = ngraph::helpers::interpreterFunction(fnPtr, {inData}); - - float thr1, thr2; - FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32, thr1, thr2); - - std::vector inShapeLimited{size_t(bsz), 4, 20, 20}; - size_t outElementsCount = std::accumulate(begin(inShapeLimited), end(inShapeLimited), 1, std::multiplies()); - FuncTestUtils::compareRawBuffers(outRawData, reinterpret_cast(refOutData[0].data()), - outElementsCount, outElementsCount, - FuncTestUtils::CompareType::ABS_AND_REL, - thr1, thr2); -} - -std::string getTestCaseName(TestParamInfo obj) { - return obj.param.deviceName + "_" + std::to_string(obj.param.batch_limit) - + "_" + std::to_string(obj.param.cur_batch); -} diff --git a/inference-engine/tests_deprecated/functional/shared_tests/input_tests/parser_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/input_tests/parser_tests.hpp index 0222e8678fc..0b948654fc8 100644 --- a/inference-engine/tests_deprecated/functional/shared_tests/input_tests/parser_tests.hpp +++ b/inference-engine/tests_deprecated/functional/shared_tests/input_tests/parser_tests.hpp @@ -7,7 +7,6 @@ #include #include #include - #include "common_test_utils/xml_net_builder/xml_net_builder.hpp" struct layer_params { diff --git a/inference-engine/tests_deprecated/functional/shared_tests/io_blob_tests/cropResize_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/io_blob_tests/cropResize_tests.hpp index 8de15d34b17..7000bedee25 100644 --- a/inference-engine/tests_deprecated/functional/shared_tests/io_blob_tests/cropResize_tests.hpp +++ b/inference-engine/tests_deprecated/functional/shared_tests/io_blob_tests/cropResize_tests.hpp @@ -11,7 +11,6 @@ #include #include "tests_common.hpp" -#include "tests_common_func.hpp" #include "format_reader_ptr.h" #include "single_layer_common.hpp" diff --git a/inference-engine/tests_deprecated/functional/shared_tests/lstm/lstm_ir_test.hpp b/inference-engine/tests_deprecated/functional/shared_tests/lstm/lstm_ir_test.hpp deleted file mode 100644 index ca1d9fcac16..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/lstm/lstm_ir_test.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "plg_test.hpp" - -#include -#include -#include - -// library taken from https://github.com/llohse/libnpy -#include "npy.hpp" - -using namespace ::testing; -using namespace InferenceEngine; - -struct ModelInfo { - std::string dir, xml, bin; -}; - -class LSTM_IR_Test : public PlgTest { -protected: - virtual void SetUp() { - PlgTest::SetUp(); - auto p = param(); - } -}; - -TEST_P(LSTM_IR_Test, canParseLSTM) { - auto fn_ptr = ngraph::builder::subgraph::makeTIwithLSTMcell(); - CNNNetwork net(fn_ptr); - - Core ie; - auto exec_net = ie.LoadNetwork(net, device_name); - auto inf_req = exec_net.CreateInferRequest(); - - auto _load_from_npy = [&](std::string name) { - std::replace(name.begin(), name.end(), '\\', '_'); - std::replace(name.begin(), name.end(), '/', '_'); - auto file_path = name + ".npy"; - - std::ifstream npy_file(file_path); - std::vector npy_shape; - std::vector npy_data; - if (npy_file.good()) - npy::LoadArrayFromNumpy(file_path, npy_shape, npy_data); - - return npy_data; - }; - - // auto _save_to_npy = [&](std::string name, - // const std::vector& npy_shape, - // const std::vector& npy_data) { - // std::replace(name.begin(), name.end(), '\\', '_'); - // std::replace(name.begin(), name.end(), '/', '_'); - // auto file_path = name + ".npy"; - - // npy::SaveArrayAsNumpy(file_path, false, (unsigned int)(npy_shape.size()), npy_shape.data(), npy_data); - // }; - - for (auto &info: net.getInputsInfo()) { - auto blob = inf_req.GetBlob(info.first); - auto npy = _load_from_npy(info.first); - - if (!npy.empty()) - std::copy_n(npy.data(), npy.size(), blob->buffer().as()); - } - - inf_req.Infer(); - - for (auto &info : net.getOutputsInfo()) { - auto blob = inf_req.GetBlob(info.first); - auto npy = _load_from_npy(info.first); - - if (!npy.empty()) - TestsCommon::compare(blob->buffer().as(), npy.data(), npy.size()); - - /* auto dims = blob->dims(); - - std::vector shape; - for (auto d : dims) shape.push_back(d); - - std::vector npy_data(blob->buffer().as(), blob->buffer().as() + blob->size()); - _save_to_npy(plugin_name + "_" + info.first, shape, npy_data); */ - } -} - -static std::vector workload = { -/* Directory | XML name | Bin name */ -{"Basic_LSTM_S/FP32", "Basic_LSTM_S"}, -}; diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/bin_conv_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/bin_conv_tests.hpp deleted file mode 100644 index 170378f6647..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/bin_conv_tests.hpp +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -#include "tests_common.hpp" -#include "single_layer_common.hpp" -#include -#include - -using namespace ::testing; -using namespace InferenceEngine; -using std::vector; - -struct bin_conv_base_params { - vector in_dims; - vector kernel; - vector strides; - vector pads_begin; - vector pads_end; - vector dilations; - - size_t out_c; - size_t grp_c; - - vector out_dims; - - float pad_value; -}; - -struct bin_conv_test_params : bin_conv_base_params { - std::string device_name; - - bin_conv_test_params(std::string name, bin_conv_base_params params) : - bin_conv_base_params(params), device_name(name) {} - -}; - -class BinaryConvolutionOnlyTest : public TestsCommon, - public WithParamInterface { - - std::string model_t_4D = R"V0G0N( - - - - - - _IN_ - _IC_ - _IH_ - _IW_ - - - - - - - - - - - _IN_ - _IC_ - _IH_ - _IW_ - - - - - _IN_ - _OC_ - _OH_ - _OW_ - - - - - - - - -)V0G0N"; - -protected: - - static void fill_data_bin(float *data, size_t size) { - for (size_t i = 0; i < size; i++) { - data[i] = sinf((float)i) > 0.f ? 1.f : -1.f; - } - } - - static void fill_data_bin_packed(int8_t *data, size_t size) { - int nbits = 8; - for (size_t i = 0; i < div_up(size, nbits); i++) { - data[i] = static_cast(i % 255); - } - } - - size_t calculateOutDim(size_t in_dim, size_t kernel, size_t stride, size_t pad_begin) { - return (in_dim + 2lu * pad_begin - kernel) / stride + 1lu; - } - - void createBlobs(const bin_conv_test_params &p, TBlob::Ptr &src, TBlob::Ptr &dst, TBlob::Ptr &dst_ref) { - auto in_size = p.in_dims.size(); - auto out_size = p.out_dims.size(); - SizeVector dims_src; - for (int i = in_size; i > 0; i--) { - dims_src.insert(dims_src.begin(), p.in_dims[i - 1]); - } - - SizeVector dims_dst = { - 1lu, - p.out_c, - p.out_dims[out_size - 2] == 0 ? calculateOutDim(p.in_dims[in_size - 2], p.kernel[Y_AXIS], p.strides[Y_AXIS], p.pads_begin[Y_AXIS]) : p.out_dims[out_size - 2], - p.out_dims[out_size - 1] == 0 ? calculateOutDim(p.in_dims[in_size - 1], p.kernel[X_AXIS], p.strides[X_AXIS], p.pads_begin[X_AXIS]) : p.out_dims[out_size - 1] - }; - - Layout layout = NCHW; - if (in_size == 5) { - layout = NCDHW; - - dims_dst.insert(dims_dst.begin() + 3, - p.out_dims.size() > 2 ? - (p.out_dims[out_size - 3] == 0 ? - calculateOutDim(p.in_dims[in_size - 3], p.kernel[Z_AXIS], p.strides[Z_AXIS], p.pads_begin[Z_AXIS]) : p.out_dims[out_size - 3]) : 1lu); - } - - src = make_shared_blob({Precision::FP32, dims_src, layout}); - src->allocate(); - - dst = make_shared_blob({Precision::FP32, dims_dst, layout}); - dst->allocate(); - - dst_ref = make_shared_blob({Precision::FP32, dims_dst, layout}); - dst_ref->allocate(); - } - - TBlob::Ptr fillWeights(const bin_conv_test_params &p) { - auto KZ = p.kernel.size() > Z_AXIS ? p.kernel[Z_AXIS] : 1lu; - TBlob *weights_ptr = new TBlob({Precision::BIN, - {(p.kernel[X_AXIS] * p.kernel[Y_AXIS] * KZ * p.out_c * p.in_dims[1] / p.grp_c + p.out_c)}, - Layout::C}); - weights_ptr->allocate(); - fill_data_bin_packed(weights_ptr->buffer(), weights_ptr->size()); - return TBlob::Ptr(weights_ptr); - } - - - struct bin_conv_common_params { - InferenceEngine::PropertyVector stride; - InferenceEngine::PropertyVector kernel; - InferenceEngine::PropertyVector pads_begin; - InferenceEngine::PropertyVector pads_end; - InferenceEngine::PropertyVector dilation; - std::string auto_pad; - size_t group; - size_t out_c; - float pad_value; - }; - - void ref_bin_conv_common(const Blob& src, - Blob& dst, - const uint8_t* weights_data, - const bin_conv_common_params& prm) { - if (src.getTensorDesc().getLayout() != Layout::NCHW && - dst.getTensorDesc().getLayout() != Layout::NCDHW) - IE_THROW() << "Reference FP32 convolution supports NCHW and NCDHW layouts only"; - size_t KW = prm.kernel[X_AXIS]; - size_t KH = prm.kernel[Y_AXIS]; - size_t KD = prm.kernel.size() > Z_AXIS ? prm.kernel[Z_AXIS] : 1lu; - - size_t SW = prm.stride[X_AXIS]; - size_t SH = prm.stride[Y_AXIS]; - size_t SD = prm.stride.size() > Z_AXIS ? prm.stride[Z_AXIS] : 0lu; - - size_t DW = prm.dilation[X_AXIS]; - size_t DH = prm.dilation[Y_AXIS]; - size_t DD = prm.dilation.size() > Z_AXIS ? prm.dilation[Z_AXIS] : 0lu; - - size_t PW = prm.pads_begin[X_AXIS]; - size_t PH = prm.pads_begin[Y_AXIS]; - size_t PD = prm.pads_begin.size() > Z_AXIS ? prm.pads_begin[Z_AXIS] : 0lu; - - size_t GC = prm.group; - - auto src_dims = src.getTensorDesc().getDims(); - size_t IW, IH, ID, IC = src_dims[1]; - - if (src_dims.size() == 5lu) { - IW = src_dims[4]; - IH = src_dims[3]; - ID = src_dims[2]; - } else { - IW = src_dims[3]; - IH = src_dims[2]; - ID = 1lu; - } - - auto dst_dims = dst.getTensorDesc().getDims(); - size_t OW, OH, OD; - size_t OC = prm.out_c; - - if (dst_dims.size() == 5lu) { - OW = dst_dims[4]; - OH = dst_dims[3]; - OD = dst_dims[2]; - } - else { - OW = dst_dims[3]; - OH = dst_dims[2]; - OD = 1lu; - } - - const auto* src_data = src.cbuffer().as(); - auto* dst_data = dst.buffer().as(); - - int nbits = 8; - - auto extract_weights = [](uint8_t val, uint8_t bit) -> float { - return (uint8_t)((val >> bit) & 0x0001) == 1 ? 1.f : -1.f; - }; - - for (uint32_t g = 0; g < GC; g++) { - for (uint32_t oc = 0; oc < OC / GC; oc++) { - for (uint32_t od = 0; od < OD; od++) { - for (uint32_t oh = 0; oh < OH; oh++) { - for (uint32_t ow = 0; ow < OW; ow++) { - size_t oidx = g * OC / GC * OD * OH * OW - + oc * OD * OH * OW - + od * OH * OW - + oh * OW - + ow; - - dst_data[oidx] = 0.f; - - for (size_t ic = 0; ic < IC / GC; ic++) { - for (size_t kd = 0; kd < KD; kd++) { - for (size_t kh = 0; kh < KH; kh++) { - for (size_t kw = 0; kw < KW; kw++) { - size_t widx = g * OC / GC * IC / GC * KD * KH * KW - + oc * IC / GC * KD * KH * KW - + ic * KD * KH * KW - + kd * KH * KW - + kh * KW - + kw; - float w = extract_weights(weights_data[widx/nbits], (uint8_t)(widx % nbits)); - - float s; - - int32_t iw = ow * SW - PW + kw * DW; - int32_t ih = oh * SH - PH + kh * DH; - int32_t id = od * SD - PD + kd * DD; - if (iw < 0 || iw >= (int32_t) IW || - ih < 0 || ih >= (int32_t) IH || - id < 0 || id >= (int32_t) ID) { - s = prm.pad_value; - } else { - size_t iidx = g * IC / GC * ID * IH * IW - + ic * ID * IH * IW - + id * IH * IW - + ih * IW - + iw; - s = src_data[iidx]; - } - - dst_data[oidx] += s * w; - } - } - } - } - } - } - } - } - } - } - - void calculateRef(const TBlob::Ptr &weights, const bin_conv_test_params &p, const TBlob::Ptr &src, - TBlob::Ptr &dst_ref) { - const uint8_t *weights_data = (const uint8_t *)weights->buffer(); - size_t bias_size = p.out_c; - bin_conv_common_params params; - for (int i = 0; i < p.kernel.size(); i++) - params.kernel.insert(i, p.kernel[i]); - for (int i = 0; i < p.strides.size(); i++) - params.stride.insert(i, p.strides[i]); - for (int i = 0; i < p.pads_begin.size(); i++) - params.pads_begin.insert(i, p.pads_begin[i]); - for (int i = 0; i < p.dilations.size(); i++) - params.dilation.insert(i, p.dilations[i]); - params.group = p.grp_c; - params.out_c = p.out_c; - params.pad_value = p.pad_value; - - ref_bin_conv_common(*src.get(), *dst_ref.get(), weights_data, params); - } - - CNNNetwork getNetwork(const TBlob::Ptr &weights, const bin_conv_test_params &p) { - Core ie; - return ie.ReadNetwork(getModel(p), weights); - } - - virtual void - infer(CNNNetwork &network, const bin_conv_test_params &p, TBlob::Ptr &src, TBlob::Ptr &dst) { - Core ie; - ExecutableNetwork executable_network = ie.LoadNetwork(network, p.device_name); - InferRequest inferRequest = executable_network.CreateInferRequest(); - - InputsDataMap inputInfo(network.getInputsInfo()); - inferRequest.SetBlob(inputInfo.begin()->first, src); - - OutputsDataMap outputInfo(network.getOutputsInfo()); - inferRequest.SetBlob(outputInfo.begin()->first, dst); - - inferRequest.Infer(); - } - - void SetUp() override { - try { - auto p = ::testing::WithParamInterface::GetParam(); - TBlob::Ptr src, dst, dst_ref; - - createBlobs(p, src, dst, dst_ref); - fill_data_bin(src->data(), src->size()); - - auto weights = fillWeights(p); - calculateRef(weights, p, src, dst_ref); - - CNNNetwork network = getNetwork(weights, p); - infer(network, p, src, dst); - - compare(*dst, *dst_ref); - } catch (const InferenceEngine::Exception &e) { - FAIL() << e.what(); - } - } - - virtual std::string getModel(bin_conv_test_params p) { - std::string model; - auto in_dims_size = p.in_dims.size(); - model = model_t_4D; - - REPLACE_WITH_NUM(model, "_IW_", p.in_dims[in_dims_size - 1]); - REPLACE_WITH_NUM(model, "_IH_", p.in_dims[in_dims_size - 2]); - REPLACE_WITH_NUM(model, "_ID_", p.in_dims[in_dims_size - 3]); - REPLACE_WITH_NUM(model, "_IC_", p.in_dims[1]); - REPLACE_WITH_NUM(model, "_IN_", p.in_dims[0]); - - REPLACE_WITH_NUM_VECTOR_REVERSE(model, "_K_", p.kernel); - REPLACE_WITH_NUM_VECTOR_REVERSE(model, "_KS_", p.strides); - REPLACE_WITH_NUM_VECTOR_REVERSE(model, "_PB_", p.pads_begin); - REPLACE_WITH_NUM_VECTOR_REVERSE(model, "_PE_", p.pads_end); - REPLACE_WITH_NUM_VECTOR_REVERSE(model, "_DL_", p.dilations); - - auto out_dims_size = p.out_dims.size(); - REPLACE_WITH_NUM(model, "_GC_", p.grp_c); - REPLACE_WITH_NUM(model, "_OC_", p.out_c); - REPLACE_WITH_NUM(model, "_OD_", out_dims_size > 2 ? - (p.out_dims[out_dims_size - 3] == 0 ? - calculateOutDim(p.in_dims[in_dims_size - 3], p.kernel[Z_AXIS], p.strides[Z_AXIS], p.pads_begin[Z_AXIS]) : p.out_dims[out_dims_size - 3]) : - 1lu); - REPLACE_WITH_NUM(model, "_OH_", p.out_dims[out_dims_size - 2] == 0 ? - calculateOutDim(p.in_dims[in_dims_size - 2], p.kernel[Y_AXIS], p.strides[Y_AXIS], p.pads_begin[Y_AXIS]) : p.out_dims[out_dims_size - 2]); - REPLACE_WITH_NUM(model, "_OW_", p.out_dims[out_dims_size - 1] == 0 ? - calculateOutDim(p.in_dims[in_dims_size - 1], p.kernel[X_AXIS], p.strides[X_AXIS], p.pads_begin[X_AXIS]) : p.out_dims[out_dims_size - 1]); - - size_t KD = p.kernel.size() > Z_AXIS ? p.kernel[Z_AXIS] : 1lu; - - int nbits = 8; - size_t w_data_size = div_up(p.kernel[X_AXIS] * p.kernel[Y_AXIS] * KD * p.out_c * p.in_dims[1] / p.grp_c, nbits); - REPLACE_WITH_NUM(model, "_S1_", w_data_size); - - REPLACE_WITH_NUM(model, "_PV_", p.pad_value); - REPLACE_WITH_STR(model, "_M_", "xnor-popcount"); - - return model; - } -}; - -#define case_1 bin_conv_base_params({{1lu, 9lu, 32lu, 16lu}, {2lu, 4lu}, {1lu, 1lu}, {0lu, 0lu}, {0lu, 0lu}, {1lu, 1lu}, 17lu, 1lu, {0lu, 0lu}, -1.f}) -#define case_2 bin_conv_base_params({{1lu, 9lu, 32lu, 16lu}, {2lu, 4lu}, {1lu, 1lu}, {0lu, 0lu}, {0lu, 0lu}, {1lu, 1lu}, 17lu, 1lu, {0lu, 0lu}, 0.f}) -#define case_3 bin_conv_base_params({{1lu, 9lu, 32lu, 16lu}, {2lu, 4lu}, {2lu, 1lu}, {0lu, 0lu}, {0lu, 0lu}, {1lu, 1lu}, 17lu, 1lu, {0lu, 0lu}, -1.f}) -#define case_4 bin_conv_base_params({{1lu, 9lu, 32lu, 16lu}, {2lu, 4lu}, {2lu, 1lu}, {0lu, 0lu}, {0lu, 0lu}, {1lu, 1lu}, 17lu, 1lu, {0lu, 0lu}, 0.f}) -#define case_5 bin_conv_base_params({{1lu, 9lu, 32lu, 16lu}, {2lu, 4lu}, {2lu, 1lu}, {0lu, 0lu}, {0lu, 0lu}, {1lu, 1lu}, 17lu, 1lu, {0lu, 0lu}, 1.f}) -#define case_6 bin_conv_base_params({{1lu, 3lu, 40lu, 40lu}, {3lu, 3lu}, {1lu, 2lu}, {0lu, 0lu}, {0lu, 0lu}, {1lu, 1lu}, 20lu, 1lu, {0lu, 0lu}, 0.f}) -#define case_7 bin_conv_base_params({{1lu, 9lu, 16lu, 32lu}, {7lu, 7lu}, {2lu, 2lu}, {3lu, 3lu}, {0lu, 0lu}, {1lu, 1lu}, 17lu, 1lu, {0lu, 0lu}, -1.f}) -#define case_8 bin_conv_base_params({{1lu, 9lu, 16lu, 32lu}, {7lu, 7lu}, {2lu, 2lu}, {3lu, 3lu}, {0lu, 0lu}, {1lu, 1lu}, 17lu, 1lu, {0lu, 0lu}, 0.f}) -#define case_9 bin_conv_base_params({{1lu, 9lu, 16lu, 32lu}, {7lu, 7lu}, {2lu, 2lu}, {3lu, 3lu}, {0lu, 0lu}, {1lu, 1lu}, 17lu, 1lu, {0lu, 0lu}, 1.f}) -#define case_10 bin_conv_base_params({{1lu, 16lu, 40lu, 40lu}, {3lu, 3lu}, {1lu, 1lu}, {0lu, 0lu}, {0lu, 0lu}, {1lu, 1lu}, 16lu, 16lu, {0lu, 0lu}, 0.f}) -#define case_11 bin_conv_base_params({{1lu, 32lu, 16lu, 32lu}, {7lu, 7lu}, {2lu, 2lu}, {3lu, 3lu}, {0lu, 0lu}, {1lu, 1lu}, 32lu, 32lu, {0lu, 0lu}, 0.f}) -#define case_12 bin_conv_base_params({{1lu, 16lu, 40lu, 40lu}, {3lu, 3lu}, {1lu, 1lu}, {0lu, 0lu}, {0lu, 0lu}, {9lu, 9lu}, 16lu, 16lu, {0lu, 0lu}, 0.f}) -#define case_13 bin_conv_base_params({{1lu, 32lu, 16lu, 32lu}, {7lu, 7lu}, {2lu, 2lu}, {3lu, 3lu}, {0lu, 0lu}, {9lu, 9lu}, 32lu, 32lu, {0lu, 0lu}, 0.f}) -#define case_14 bin_conv_base_params({{1lu, 19lu, 16lu, 32lu}, {3lu, 3lu}, {1lu, 1lu}, {1lu, 1lu}, {1lu, 1lu}, {1lu, 1lu}, 21lu, 1lu, {0lu, 0lu}, -1.f}) -#define case_15 bin_conv_base_params({{1lu, 17lu, 16lu, 32lu}, {3lu, 3lu}, {1lu, 1lu}, {1lu, 1lu}, {1lu, 1lu}, {1lu, 1lu}, 19lu, 1lu, {0lu, 0lu}, 0.f}) -#define case_16 bin_conv_base_params({{1lu, 21lu, 16lu, 32lu}, {3lu, 3lu}, {1lu, 1lu}, {1lu, 1lu}, {1lu, 1lu}, {1lu, 1lu}, 33lu, 1lu, {0lu, 0lu}, 1.f}) - -TEST_P(BinaryConvolutionOnlyTest, TestsBinaryConvolution) { -} - -std::string getTestCaseName(testing::TestParamInfo obj) { - auto in_dims_size = obj.param.in_dims.size(); - return obj.param.device_name + - "_w" + std::to_string(obj.param.in_dims[in_dims_size - 1]) + - "_h" + std::to_string(obj.param.in_dims[in_dims_size - 2]) + - (obj.param.in_dims.size() > 4 ? "_d" + std::to_string(obj.param.in_dims[in_dims_size - 3]) : "") + - "_c" + std::to_string(obj.param.in_dims[1]) + - "_kw" + std::to_string(obj.param.kernel[X_AXIS]) + - "_kh" + std::to_string(obj.param.kernel[Y_AXIS]) + - (obj.param.kernel.size() > Z_AXIS ? "_kd" + std::to_string(obj.param.kernel[Z_AXIS]) : "") + - "_sw" + std::to_string(obj.param.strides[X_AXIS]) + - "_sh" + std::to_string(obj.param.strides[Y_AXIS]) + - (obj.param.strides.size() > Z_AXIS ? "_sd" + std::to_string(obj.param.strides[Z_AXIS]) : "") + - "_dilw" + std::to_string(obj.param.dilations[X_AXIS]) + - "_dilh" + std::to_string(obj.param.dilations[Y_AXIS]) + - (obj.param.dilations.size() > Z_AXIS ? "_dild" + std::to_string(obj.param.dilations[Z_AXIS]) : "") + - "_grpc" + std::to_string(obj.param.grp_c) + - "_pad_v" + std::to_string(obj.param.pad_value); -} diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/deformable_psroi_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/deformable_psroi_tests.hpp deleted file mode 100644 index 16f18da5fb9..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/deformable_psroi_tests.hpp +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -#include "tests_common.hpp" -#include "single_layer_common.hpp" -#include "common_test_utils/data_utils.hpp" - -using namespace ::testing; -using namespace InferenceEngine; - -struct deformable_psroi_test_params { - std::string device_name; - - std::vector src_dims; - std::vector bbox_dims; - std::vector out_dims; - float spatial_scale; - size_t output_dim; - size_t group_size; - size_t pooled_height; - size_t pooled_width; - int part_size; - int sample_per_part; - bool no_trans; - float trans_std; - std::vector trans_dims; -}; - -inline float bilinear_interp(const float* data, const float x, const float y, const int width, const int height) { - int x1 = static_cast(std::floor(x)); - int x2 = static_cast(std::ceil(x)); - int y1 = static_cast(std::floor(y)); - int y2 = static_cast(std::ceil(y)); - float dist_x = x - x1; - float dist_y = y - y1; - float value11 = data[y1 * width + x1]; - float value12 = data[y2 * width + x1]; - float value21 = data[y1 * width + x2]; - float value22 = data[y2 * width + x2]; - float value = (1 - dist_x) * (1 - dist_y) * value11 + (1 - dist_x) * dist_y * value12 - + dist_x * (1 - dist_y) * value21 + dist_x * dist_y * value22; - return value; -} - -static void ref_deformable_psroi(const std::vector &srcs, std::vector &dsts, deformable_psroi_test_params prm) { - float* dst_data = dsts[0]->buffer(); - const float *bottom_data_beginning = srcs[1]->buffer(); - const float *bottom_rois_beginning = srcs[0]->buffer(); - - SizeVector inDims = srcs[1]->getTensorDesc().getDims(); - int channels = static_cast(inDims[1]); - int height = static_cast(inDims[2]); - int width = static_cast(inDims[3]); - - SizeVector outDims = dsts[0]->getTensorDesc().getDims(); - int nn = static_cast(outDims[0]); - int nc = static_cast(outDims[1]); - int nh = static_cast(outDims[2]); - int nw = static_cast(outDims[3]); - - int real_rois = 0; - for (; real_rois < nn; real_rois++) { - const float *bottom_rois = bottom_rois_beginning + real_rois * 5; - int roi_batch_ind = static_cast(bottom_rois[0]); - if (roi_batch_ind == -1) { - break; - } - } - - float *bottom_trans = nullptr; - int num_classes = 1; - int channels_each_class = prm.output_dim; - if (srcs.size() == 3) { - bottom_trans = srcs[2]->buffer(); - num_classes = static_cast(srcs[2]->getTensorDesc().getDims()[1]) / 2; - channels_each_class /= num_classes; - } - - for (int n = 0; n < real_rois; n++) { - const float *bottom_rois = bottom_rois_beginning + n * 5; - int roi_batch_ind = static_cast(bottom_rois[0]); - float roi_start_w = static_cast(round(bottom_rois[1])) * prm.spatial_scale - 0.5; - float roi_start_h = static_cast(round(bottom_rois[2])) * prm.spatial_scale - 0.5; - float roi_end_w = static_cast(round(bottom_rois[3]) + 1.0) * prm.spatial_scale - 0.5; - float roi_end_h = static_cast(round(bottom_rois[4]) + 1.0) * prm.spatial_scale - 0.5; - float roi_width = std::max(static_cast(roi_end_w - roi_start_w), 0.1); - float roi_height = std::max(static_cast(roi_end_h - roi_start_h), 0.1); - - for (int c = 0; c < nc; c++) { - for (int h = 0; h < nh; h++) { - for (int w = 0; w < nw; w++) { - size_t index = n*nc*nh*nw + c*nh*nw + h*nw + w; - dst_data[index] = 0.0f; - - float bin_size_h = roi_height / static_cast(prm.pooled_height); - float bin_size_w = roi_width / static_cast(prm.pooled_width); - - float sub_bin_size_h = bin_size_h / static_cast(prm.sample_per_part); - float sub_bin_size_w = bin_size_w / static_cast(prm.sample_per_part); - - int part_h = static_cast(std::floor(static_cast(h) / prm.pooled_height * prm.part_size)); - int part_w = static_cast(std::floor(static_cast(w) / prm.pooled_width * prm.part_size)); - - int class_id = c / channels_each_class; - float trans_x = prm.no_trans ? 0 : - bottom_trans[(((n * num_classes + class_id) * 2) * prm.part_size + part_h) - * prm.part_size + part_w] * prm.trans_std; - float trans_y = prm.no_trans ? 0 : - bottom_trans[(((n * num_classes + class_id) * 2 + 1) * prm.part_size + part_h) - * prm.part_size + part_w] * prm.trans_std; - - float wstart = w * bin_size_w + roi_start_w + trans_x * roi_width; - float hstart = h * bin_size_h + roi_start_h + trans_y * roi_height; - - float sum = 0; - int count = 0; - int gw = (static_cast(w) * prm.group_size / prm.pooled_width ); - int gh = (static_cast(h) * prm.group_size / prm.pooled_height ); - gw = std::min(std::max(gw, 0), static_cast(prm.group_size - 1)); - gh = std::min(std::max(gh, 0), static_cast(prm.group_size - 1)); - - const float* offset_bottom_data = bottom_data_beginning + (roi_batch_ind * channels) * height * width; - for (size_t ih = 0; ih < prm.sample_per_part; ih++) { - for (size_t iw = 0; iw < prm.sample_per_part; iw++) { - float w1 = wstart + iw * sub_bin_size_w; - float h1 = hstart + ih * sub_bin_size_h; - // bilinear interpolation - if (w1 < -0.5 || w1 > width - 0.5 || h1 < -0.5 || h1 > height - 0.5) - continue; - w1 = std::min(std::max(w1, 0.0f), width - 1.0f); - h1 = std::min(std::max(h1, 0.0f), height - 1.0f); - int c1 = static_cast((c * prm.group_size + gh) * prm.group_size + gw); - float val = bilinear_interp(offset_bottom_data + c1 * height * width, w1, h1, width, height); - sum += val; - count++; - } - } - dst_data[index] = count == 0 ? 0 : sum / count; - } - } - } - } - for (int n = real_rois; n < nn; n++) { - for (int c = 0; c < nc; c++) { - for (int h = 0; h < nh; h++) { - for (int w = 0; w < nw; w++) { - int index = n * nc * nh * nw + c * nh * nw + h * nw + w; - dst_data[index] = 0.0f; - } - } - } - } -} - -class DeformablePSROIOnlyTest : public TestsCommon, - public WithParamInterface { - - std::string model_t = R"V0G0N( - - - - - __SRC_DIMS__ - - - - - - __BBOX_DIMS__ - - - __TRANS__ - - - - __SRC_DIMS__ - - __BBOX_DIMS__ - __TRANS_DIMS__ - - - __OUT_DIMS__ - - - - - - - __EDGE_TRANS__ - - -)V0G0N"; - - std::string getModel(deformable_psroi_test_params p) { - std::string model = model_t; - - std::string no_trans = "True"; - std::string trans = ""; - std::string trans_params = ""; - std::string trans_dims = ""; - std::string edge_trans = ""; - if (!p.no_trans) { - no_trans = "False"; - - trans = R"VOGON( - - __TRANS_DIMS__ - - )VOGON"; - - trans_params += " trans_std=\"" + std::to_string(p.trans_std) + "\""; - - trans_dims += "\n "; - for (auto &dim : p.trans_dims) { - trans_dims += "\n "; - trans_dims += std::to_string(dim) + ""; - } - trans_dims += "\n "; - - edge_trans = "\n "; - } - REPLACE_WITH_STR(model, "__TRANS__", trans); - REPLACE_WITH_STR(model, "__TRANS_PARAMS__", trans_params); - REPLACE_WITH_STR(model, "__TRANS_DIMS__", trans_dims); - REPLACE_WITH_STR(model, "__EDGE_TRANS__", edge_trans); - - std::string src_dims = ""; - for (auto &dim : p.src_dims) { - src_dims += "\n "; - src_dims += std::to_string(dim) + ""; - } - REPLACE_WITH_STR(model, "__SRC_DIMS__", src_dims); - std::string bbox_dims = ""; - for (auto &dim : p.bbox_dims) { - bbox_dims += "\n "; - bbox_dims += std::to_string(dim) + ""; - } - REPLACE_WITH_STR(model, "__BBOX_DIMS__", bbox_dims); - std::string out_dims = ""; - for (auto &dim : p.out_dims) { - out_dims += "\n "; - out_dims += std::to_string(dim) + ""; - } - REPLACE_WITH_STR(model, "__OUT_DIMS__", out_dims); - - REPLACE_WITH_STR(model, "__NO_TRANS__", no_trans); - REPLACE_WITH_NUM(model, "__SPATIAL_SCALE__", p.spatial_scale); - REPLACE_WITH_NUM(model, "__OUTPUT_DIM__", p.output_dim); - REPLACE_WITH_NUM(model, "__PART_SIZE__", p.part_size); - REPLACE_WITH_NUM(model, "__GROUP_SIZE__", p.group_size); - REPLACE_WITH_NUM(model, "__POOLED_HEIGHT__", p.pooled_height); - REPLACE_WITH_NUM(model, "__POOLED_WIDTH__", p.pooled_width); - REPLACE_WITH_NUM(model, "__SAMPLE_PER_PART__", p.sample_per_part); - - return model; - } - -protected: - virtual void SetUp() { - try { - deformable_psroi_test_params p = ::testing::WithParamInterface::GetParam(); - std::string model = getModel(p); - - Core ie; - CNNNetwork net = ie.ReadNetwork(model, Blob::CPtr()); - ExecutableNetwork executable_network = ie.LoadNetwork(net, p.device_name); - InferRequest inferRequest = executable_network.CreateInferRequest(); - - std::vector srcs_vec; - - InputsDataMap in_info_map = net.getInputsInfo(); - for (auto info : in_info_map) { - Blob::Ptr blob = make_shared_blob( - {Precision::FP32, info.second->getTensorDesc().getDims(), Layout::ANY}); - blob->allocate(); - if (info.second->name() == "data") { - CommonTestUtils::fill_data_sine(blob->buffer(), blob->size(), 1.0f, 5.0f, 0.1f); - } else if (info.second->name() == "bbox") { - CommonTestUtils::fill_data_bbox(blob->buffer(), blob->size(), p.src_dims[2], p.src_dims[3], 1.0f); - } else if (info.second->name() == "trans") { - CommonTestUtils::fill_data_sine(blob->buffer(), blob->size(), 0.0f, 10.0f, 1.0f); - } - - inferRequest.SetBlob(info.first, blob); - srcs_vec.push_back(blob); - } - - BlobMap dsts_map; - std::vector dsts_vec; - - OutputsDataMap out_info_map = net.getOutputsInfo(); - for (auto info : out_info_map) { - Blob::Ptr blob = make_shared_blob( - {Precision::FP32, info.second->getTensorDesc().getDims(), Layout::ANY}); - blob->allocate(); - inferRequest.SetBlob(info.first, blob); - dsts_map[info.first] = blob; - - Blob::Ptr blob_ref = make_shared_blob( - {Precision::FP32, info.second->getTensorDesc().getDims(), Layout::ANY}); - blob_ref->allocate(); - dsts_vec.push_back(blob_ref); - } - - ref_deformable_psroi(srcs_vec, dsts_vec, p); - - inferRequest.Infer(); - - TBlob* dstPtr = dynamic_cast*>(dsts_map.begin()->second.get()); - TBlob* dstrefPtr = dynamic_cast*>(dsts_vec[0].get()); - - compare(*dsts_map.begin()->second, *dsts_vec[0]); - - } catch (const InferenceEngine::Exception &e) { - FAIL() << e.what(); - } - } -}; - -TEST_P(DeformablePSROIOnlyTest, TestsDeformable) {} - -/*** TBD ***/ - - - diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/gemm_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/gemm_tests.hpp deleted file mode 100644 index 8e431ee9326..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/gemm_tests.hpp +++ /dev/null @@ -1,492 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -#include "tests_common.hpp" -#include "single_layer_common.hpp" -#include -#include -#include - -using namespace InferenceEngine; - -struct gemm_base_params { - float alpha; - float beta; - bool transpose_A; - bool transpose_B; - SizeVector dims_A; - SizeVector dims_B; - SizeVector dims_C; - - gemm_base_params() = default; - gemm_base_params(float _alpha, - float _beta, - bool _transpose_A, - bool _transpose_B, - SizeVector _dims_A, - SizeVector _dims_B, - SizeVector _dims_C = {}) - : alpha(_alpha) - , beta(_beta) - , transpose_A(_transpose_A) - , transpose_B(_transpose_B) - , dims_A(_dims_A) - , dims_B(_dims_B) - , dims_C(_dims_C) - {} - - virtual void print(std::ostream& os) const { - os << "alpha: " << alpha << ", beta: " << beta - << ", trans A: " << transpose_A << ", trans B: " << transpose_B - << std::endl; - - auto print_dims = [&](std::string name, const SizeVector& dims) { - os << name << ": {"; - if (!dims.empty()) - os << dims[0]; - for (size_t i = 1; i < dims.size(); ++i) - os << ", " << dims[i]; - os << "}" << std::endl; - }; - - print_dims("A", dims_A); - print_dims("B", dims_B); - print_dims("C", dims_C); - } - - virtual SizeVector outDims() const { - size_t max_dims_num = std::max(dims_A.size(), dims_B.size()); - max_dims_num = std::max(dims_C.size(), max_dims_num); - - SizeVector dims_out(max_dims_num); - // Process batch dims in reverse for required alignment - for (size_t rbi = 0; rbi < max_dims_num - 2; ++rbi) { - size_t max_val = 1; - - if (rbi + 2 < dims_A.size()) { - auto bi_A = dims_A.size() - rbi - 3; - max_val = std::max(max_val, dims_A[bi_A]); - } - if (rbi + 2 < dims_B.size()) { - auto bi_B = dims_B.size() - rbi - 3; - max_val = std::max(max_val, dims_B[bi_B]); - } - if (rbi + 2 < dims_C.size()) { - auto bi_C = dims_C.size() - rbi - 3; - max_val = std::max(max_val, dims_C[bi_C]); - } - - auto bi_out = max_dims_num - rbi - 3; - dims_out[bi_out] = max_val; - } - - auto y_dim_A = transpose_A ? dims_A.size() - 1 : dims_A.size() - 2; - auto x_dim_B = transpose_B ? dims_B.size() - 2 : dims_B.size() - 1; - dims_out[dims_out.size() - 1] = dims_B[x_dim_B]; - dims_out[dims_out.size() - 2] = dims_A[y_dim_A]; - - return dims_out; - } -}; - - -std::vector ref_gemm(const gemm_base_params& params, - const std::vector& data_A, - const std::vector& data_B, - const std::vector& data_C) { - const auto& dims_A = params.dims_A; - const auto& dims_B = params.dims_B; - const auto& dims_C = params.dims_C; - - bool use_C = !dims_C.empty(); - - auto x_A = dims_A[dims_A.size() - 1]; - auto y_A = dims_A[dims_A.size() - 2]; - auto x_pitch_A = size_t(1); - auto y_pitch_A = x_A; - - auto x_B = dims_B[dims_B.size() - 1]; - auto y_B = dims_B[dims_B.size() - 2]; - auto x_pitch_B = size_t(1); - auto y_pitch_B = x_B; - - if (params.transpose_A) { - std::swap(x_A, y_A); - std::swap(x_pitch_A, y_pitch_A); - } - - if (params.transpose_B) { - std::swap(x_B, y_B); - std::swap(x_pitch_B, y_pitch_B); - } - - auto dims_out = params.outDims(); - - auto x_out = dims_out[dims_out.size() - 1]; - auto y_out = dims_out[dims_out.size() - 2]; - auto x_pitch_out = size_t(1); - auto y_pitch_out = x_out; - - auto out_batch_num = dims_out.size() - 2; - - // Calculates batch pitches in reverse order - auto calculate_batch_pitches = [out_batch_num](const SizeVector& dims) { - std::vector batch_pitches = { }; - batch_pitches.reserve(out_batch_num); - size_t real_pitch = dims[dims.size() - 2] * dims[dims.size() - 1]; - - for (size_t rbi = 0; rbi < out_batch_num; ++rbi) { - if (rbi + 2 < dims.size() && dims[dims.size() - rbi - 3] != 1) { - batch_pitches.push_back(real_pitch); - real_pitch *= dims[dims.size() - rbi - 3]; - } else { - // Set to zero for broadcasting - batch_pitches.push_back(0ul); - } - } - - return batch_pitches; - }; - - auto batch_pitches_A = calculate_batch_pitches(dims_A); - auto batch_pitches_B = calculate_batch_pitches(dims_B); - auto batch_pitches_C = use_C ? calculate_batch_pitches(dims_C) : std::vector(); - auto batch_pitches_out = calculate_batch_pitches(dims_out); - - auto k = x_A; - - auto total_out_size = std::accumulate(dims_out.begin(), dims_out.end(), 1ul, std::multiplies()); - std::vector data_out(total_out_size, 0.f); - - // Currently processed batch indices in reverse order - std::vector current_batch_indices(out_batch_num, 0ul); - auto get_current_batch_offset = [&](const std::vector& pitches) { - return std::inner_product(pitches.begin(), pitches.end(), current_batch_indices.begin(), 0ul); - }; - - do { - auto batch_offset_A = get_current_batch_offset(batch_pitches_A); - auto batch_offset_B = get_current_batch_offset(batch_pitches_B); - auto batch_offset_C = use_C ? get_current_batch_offset(batch_pitches_C) : 0ul; - auto batch_offset_out = get_current_batch_offset(batch_pitches_out); - - for (size_t yi = 0; yi < y_out; ++yi) { - for (size_t xi = 0; xi < x_out; ++xi) { - - float acc = 0.f; - if (params.alpha != 0.f) { - for (size_t ki = 0; ki < k; ++ki) { - auto idx_A = batch_offset_A + yi * y_pitch_A + ki * x_pitch_A; - auto idx_B = batch_offset_B + ki * y_pitch_B + xi * x_pitch_B; - - acc += data_A[idx_A] * data_B[idx_B]; - } - - acc *= params.alpha; - } - - if (use_C && params.beta != 0.f) { - auto idx_C = batch_offset_C + yi * y_pitch_out + xi * x_pitch_out; - acc += params.beta * data_C[idx_C]; - } - - auto idx_out = batch_offset_out + yi * y_pitch_out + xi * x_pitch_out; - data_out[idx_out] = acc; - } - } - - for (size_t i = 0; i < out_batch_num; ++i) { - current_batch_indices[i] += 1; - if (current_batch_indices[i] == dims_out[dims_out.size() - 3 - i] && - i != out_batch_num - 1) { // Don't reset last index as it signals end of calculations - current_batch_indices[i] = 0; - } else { - break; - } - } - } while (current_batch_indices.size() > 0 && - current_batch_indices[current_batch_indices.size() - 1] != dims_out[0]); - - return data_out; -} - -struct gemm_test_params : gemm_base_params { - std::string device_name; - std::string precision; - - gemm_test_params(std::string name, std::string _precision, gemm_base_params base) - : gemm_base_params(base) - , device_name(name) - , precision(_precision) - {} - - gemm_test_params(std::tuple wrapper) - : gemm_test_params(std::get<0>(wrapper), std::get<1>(wrapper), std::get<2>(wrapper)) - {} - - void print(std::ostream& os) const override { - os << "Device: " << device_name << ", precision: " << precision << std::endl; - gemm_base_params::print(os); - } -}; - -class GemmTestBase : public TestsCommon { - std::string model_t = R"V0G0N( - - - - - - _IN_A_DIMS_ - - - - - - - _IN_B_DIMS_ - - - - _IN_C_LAYER_ - - - - - _IN_A_DIMS_ - - - _IN_B_DIMS_ - - _IN_C_GEMM_PORT_ - - - - _OUT_DIMS_ - - - - - - - - _IN_C_EDGE_ - - -)V0G0N"; - -std::string in_C_layer = R"V0G0N( - - - - _IN_C_DIMS_ - - - -)V0G0N"; - -std::string in_C_port = R"V0G0N( - - _IN_C_DIMS_ - -)V0G0N"; - -std::string in_C_edge = R"V0G0N( - -)V0G0N"; - -protected: - virtual float getThreshold(const gemm_test_params& params) { - if (params.precision == "FP16") - return 0.02f; - else - return 0.01f; - } - - std::string getModel(const gemm_test_params& params) { - auto model = model_t; - - if (!params.dims_C.empty()) { - REPLACE_WITH_STR(model, "_IN_C_LAYER_", in_C_layer); - REPLACE_WITH_STR(model, "_IN_C_GEMM_PORT_", in_C_port); - REPLACE_WITH_STR(model, "_IN_C_EDGE_", in_C_edge); - } else { - REPLACE_WITH_STR(model, "_IN_C_LAYER_", ""); - REPLACE_WITH_STR(model, "_IN_C_GEMM_PORT_", ""); - REPLACE_WITH_STR(model, "_IN_C_EDGE_", ""); - } - - REPLACE_WITH_STR(model, "_PRECISION_", params.precision); - - REPLACE_WITH_NUM(model, "_ALPHA_", params.alpha); - REPLACE_WITH_NUM(model, "_BETA_", params.beta); - REPLACE_WITH_NUM(model, "_TRANS_A_", params.transpose_A); - REPLACE_WITH_NUM(model, "_TRANS_B_", params.transpose_B); - - auto get_dims_str = [](const SizeVector& dims) { - std::string result; - for (const auto& d : dims) { - result += "" + std::to_string(d) + "\n"; - } - return result; - }; - - std::string in_A_dims = get_dims_str(params.dims_A); - std::string in_B_dims = get_dims_str(params.dims_B); - std::string in_C_dims = get_dims_str(params.dims_C); - std::string out_dims = get_dims_str(params.outDims()); - - REPLACE_WITH_STR(model, "_IN_A_DIMS_", in_A_dims); - REPLACE_WITH_STR(model, "_IN_B_DIMS_", in_B_dims); - REPLACE_WITH_STR(model, "_IN_C_DIMS_", in_C_dims); - REPLACE_WITH_STR(model, "_OUT_DIMS_", out_dims); - - return model; - } - - CNNNetwork getNetwork(Core & ie, const gemm_test_params& params) { - std::string model = getModel(params); - - CNNNetwork network = ie.ReadNetwork(model, Blob::CPtr()); - - network.getInputsInfo().at("input_A")->setPrecision(Precision::FP32); - network.getInputsInfo().at("input_B")->setPrecision(Precision::FP32); - if (!params.dims_C.empty()) - network.getInputsInfo().at("input_C")->setPrecision(Precision::FP32); - - network.getOutputsInfo().at("gemm")->setPrecision(Precision::FP32); - - return network; - } - - void runTest(const gemm_test_params& test_params, - const std::vector& data_A, - const std::vector& data_B, - const std::vector& data_C, - const std::vector& ref_output) { - test_params.print(std::cout); - - Core ie; - auto network = getNetwork(ie, test_params); - auto exec = ie.LoadNetwork(network, test_params.device_name); - auto request = exec.CreateInferRequest(); - - auto fill_blob = [&](const char* name, const std::vector& data) { - Blob::Ptr blob = request.GetBlob(name); - - auto fill_size = std::min(blob->size(), data.size()); - auto buffer = blob->buffer().as(); - - for (size_t i = 0; i < fill_size; ++i) { - buffer[i] = data[i]; - } - }; - - fill_blob("input_A", data_A); - fill_blob("input_B", data_B); - if (!test_params.dims_C.empty()) { - fill_blob("input_C", data_C); - } - - request.Infer(); - - if (!ref_output.empty()) { - Blob::Ptr blob_out = request.GetBlob("gemm"); - ASSERT_EQ(blob_out->size(), ref_output.size()); - - auto buf_out = blob_out->buffer().as(); - compare(buf_out, ref_output.data(), blob_out->size(), getThreshold(test_params)); - } - } -}; - -using GemmRandomTestParam = std::tuple< - std::string, // plugin - std::string, // precision - gemm_base_params>; // gemm params - -class GemmRandomTest : public GemmTestBase, public testing::WithParamInterface {}; - -// Basic cases: all transposition combinations, 2D-5D -#define case1 gemm_base_params(1.2f, 3.f, false, false, {9ul, 11ul}, {11ul, 13ul} ) -#define case2 gemm_base_params(1.2f, 3.f, false, false, {9ul, 11ul}, {11ul, 13ul}, {9ul, 13ul} ) -#define case3 gemm_base_params(2.5f, 1.2f, false, false, {7ul, 9ul, 11ul}, {7ul, 11ul, 13ul} ) -#define case4 gemm_base_params(2.5f, 1.2f, false, false, {7ul, 9ul, 11ul}, {7ul, 11ul, 13ul}, {7ul, 9ul, 13ul} ) -#define case5 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}) -#define case6 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}, {3ul, 7ul, 9ul, 13ul} ) -#define case7 gemm_base_params(1.2f, -1.5f, false, false, {2ul, 3ul, 7ul, 9ul, 11ul}, {2ul, 3ul, 7ul, 11ul, 13ul}) -#define case8 gemm_base_params(1.2f, -1.5f, false, false, {2ul, 3ul, 7ul, 9ul, 11ul}, {2ul, 3ul, 7ul, 11ul, 13ul}, {2ul, 3ul, 7ul, 9ul, 13ul}) -#define case9 gemm_base_params(1.2f, 3.f, true, false, {11ul, 9ul}, {11ul, 13ul} ) -#define case10 gemm_base_params(1.2f, 3.f, true, false, {11ul, 9ul}, {11ul, 13ul}, {9ul, 13ul} ) -#define case11 gemm_base_params(2.5f, 1.2f, true, false, {7ul, 11ul, 9ul}, {7ul, 11ul, 13ul} ) -#define case12 gemm_base_params(2.5f, 1.2f, true, false, {7ul, 11ul, 9ul}, {7ul, 11ul, 13ul}, {7ul, 9ul, 13ul} ) -#define case13 gemm_base_params(1.2f, -1.5f, true, false, {3ul, 7ul, 11ul, 9ul}, {3ul, 7ul, 11ul, 13ul}) -#define case14 gemm_base_params(1.2f, -1.5f, true, false, {3ul, 7ul, 11ul, 9ul}, {3ul, 7ul, 11ul, 13ul}, {3ul, 7ul, 9ul, 13ul} ) -#define case15 gemm_base_params(1.2f, -1.5f, true, false, {2ul, 3ul, 7ul, 11ul, 9ul}, {2ul, 3ul, 7ul, 11ul, 13ul}) -#define case16 gemm_base_params(1.2f, -1.5f, true, false, {2ul, 3ul, 7ul, 11ul, 9ul}, {2ul, 3ul, 7ul, 11ul, 13ul}, {2ul, 3ul, 7ul, 9ul, 13ul}) -#define case17 gemm_base_params(1.2f, 3.f, false, true, {9ul, 11ul}, {13ul, 11ul} ) -#define case18 gemm_base_params(1.2f, 3.f, false, true, {9ul, 11ul}, {13ul, 11ul}, {9ul, 13ul} ) -#define case19 gemm_base_params(2.5f, 1.2f, false, true, {7ul, 9ul, 11ul}, {7ul, 13ul, 11ul} ) -#define case20 gemm_base_params(2.5f, 1.2f, false, true, {7ul, 9ul, 11ul}, {7ul, 13ul, 11ul}, {7ul, 9ul, 13ul} ) -#define case21 gemm_base_params(1.2f, -1.5f, false, true, {3ul, 7ul, 9ul, 11ul}, {3ul, 7ul, 13ul, 11ul}) -#define case22 gemm_base_params(1.2f, -1.5f, false, true, {3ul, 7ul, 9ul, 11ul}, {3ul, 7ul, 13ul, 11ul}, {3ul, 7ul, 9ul, 13ul} ) -#define case23 gemm_base_params(1.2f, -1.5f, false, true, {2ul, 3ul, 7ul, 9ul, 11ul}, {2ul, 3ul, 7ul, 13ul, 11ul}) -#define case24 gemm_base_params(1.2f, -1.5f, false, true, {2ul, 3ul, 7ul, 9ul, 11ul}, {2ul, 3ul, 7ul, 13ul, 11ul}, {2ul, 3ul, 7ul, 9ul, 13ul}) -#define case25 gemm_base_params(1.2f, 3.f, true, true, {11ul, 9ul}, {13ul, 11ul} ) -#define case26 gemm_base_params(1.2f, 3.f, true, true, {11ul, 9ul}, {13ul, 11ul}, {9ul, 13ul} ) -#define case27 gemm_base_params(2.5f, 1.2f, true, true, {7ul, 11ul, 9ul}, {7ul, 13ul, 11ul} ) -#define case28 gemm_base_params(2.5f, 1.2f, true, true, {7ul, 11ul, 9ul}, {7ul, 13ul, 11ul}, {7ul, 9ul, 13ul} ) -#define case29 gemm_base_params(1.2f, -1.5f, true, true, {3ul, 7ul, 11ul, 9ul}, {3ul, 7ul, 13ul, 11ul}) -#define case30 gemm_base_params(1.2f, -1.5f, true, true, {3ul, 7ul, 11ul, 9ul}, {3ul, 7ul, 13ul, 11ul}, {3ul, 7ul, 9ul, 13ul} ) -#define case31 gemm_base_params(1.2f, -1.5f, true, true, {2ul, 3ul, 7ul, 11ul, 9ul}, {2ul, 3ul, 7ul, 13ul, 11ul}) -#define case32 gemm_base_params(1.2f, -1.5f, true, true, {2ul, 3ul, 7ul, 11ul, 9ul}, {2ul, 3ul, 7ul, 13ul, 11ul}, {2ul, 3ul, 7ul, 9ul, 13ul}) - -// Broadcasting/dimension inference cases -#define case33 gemm_base_params(1.2f, -1.5f, false, false, {1ul, 1ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}) -#define case34 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {1ul, 1ul, 11ul, 13ul}) -#define case35 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}, {1ul, 1ul, 9ul, 13ul}) -#define case36 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 1ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}) -#define case37 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {3ul, 1ul, 11ul, 13ul}) -#define case38 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}, {3ul, 1ul, 9ul, 13ul}) -#define case39 gemm_base_params(1.2f, -1.5f, false, false, {9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}) -#define case40 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {11ul, 13ul}) -#define case41 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}, {9ul, 13ul}) -#define case42 gemm_base_params(1.2f, -1.5f, false, false, {7ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}) -#define case43 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {7ul, 11ul, 13ul}) -#define case44 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 7ul, 9ul, 11ul}, {3ul, 7ul, 11ul, 13ul}, {7ul, 9ul, 13ul}) -#define case45 gemm_base_params(1.2f, -1.5f, false, false, {7ul, 9ul, 11ul}, {3ul, 1ul, 11ul, 13ul}) -#define case46 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 1ul, 9ul, 11ul}, {7ul, 11ul, 13ul}) -#define case47 gemm_base_params(1.2f, -1.5f, false, false, {3ul, 1ul, 9ul, 11ul}, {3ul, 1ul, 11ul, 13ul}, {7ul, 9ul, 13ul}) - -#define all_cases \ - case1, case2, case3, case4, case5, case6, case7, case8, \ - case9, case10, case11, case12, case13, case14, case15, case16, \ - case17, case18, case19, case20, case21, case22, case23, case24, \ - case25, case26, case27, case28, case29, case30, case31, case32, \ - case33, case34, case35, case36, case37, case38, \ - case39, case40, case41, case42, case43, case44, \ - case45, case46, case47 - -TEST_P(GemmRandomTest, smoke_randomInput) { - gemm_test_params params = GetParam(); - - auto size_A = std::accumulate(params.dims_A.begin(), params.dims_A.end(), size_t(1), std::multiplies()); - auto size_B = std::accumulate(params.dims_B.begin(), params.dims_B.end(), size_t(1), std::multiplies()); - auto size_C = std::accumulate(params.dims_C.begin(), params.dims_C.end(), size_t(1), std::multiplies()); - - std::vector data_A(size_A); - std::vector data_B(size_B); - std::vector data_C(size_C); - - fill_data(data_A.data(), size_A); - fill_data(data_B.data(), size_B); - fill_data(data_C.data(), size_C); - - auto ref_output = ref_gemm(params, data_A, data_B, data_C); - - runTest(params, data_A, data_B, data_C, ref_output); -}; diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/one_hot_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/one_hot_tests.hpp deleted file mode 100644 index 0c62b519b3d..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/one_hot_tests.hpp +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -#include "tests_common.hpp" -#include "single_layer_common.hpp" -#include - -using namespace ::testing; -using namespace InferenceEngine; -using namespace std; - -struct one_hot_base_params { - std::vector in; - std::vector out; - int axis; - unsigned int depth; - float on, off; -}; - -struct one_hot_test_params : one_hot_base_params { - std::string device_name; - - one_hot_test_params(std::string name, one_hot_base_params params) : - one_hot_base_params(params), device_name(name) {} -}; - -class OneHotOnlyTestShared: public TestsCommon, - public WithParamInterface { - - std::string model_t = R"V0G0N( - - - - - - _IN_ - - - - - - - - - - _IN_ - - - - - _OUT_ - - - - - l - - - -)V0G0N"; - - std::string getModel(one_hot_test_params p) { - std::string model = model_t; - - std::string in_shape; - std::string out_shape; - - for (size_t i = 0; i < p.in.size(); i++) { - in_shape += ""; - in_shape += std::to_string(p.in[i]) + "\n"; - } - for (size_t i = 0; i < p.out.size(); i++) { - out_shape += ""; - out_shape += std::to_string(p.out[i]) + "\n"; - } - - - REPLACE_WITH_STR(model, "_IN_", in_shape); - REPLACE_WITH_STR(model, "_OUT_", out_shape); - - REPLACE_WITH_NUM(model, "_AXIS_", p.axis); - REPLACE_WITH_NUM(model, "_DEPTH_", p.depth); - - return model; - } - - void ref_one_hot_4d(Blob &src, Blob &dst, one_hot_test_params p) - { - float *src_ptr = src.buffer().as(); - std::size_t src_size = src.size(); - float *dst_ptr = dst.buffer().as(); - std::size_t dst_size = dst.size(); - - int out_n = (p.out.size() >= 1) ? p.out[0] : 1; - int out_c = (p.out.size() >= 2) ? p.out[1] : 1; - int out_d = (p.out.size() == 5) ? p.out[2] : 1; - int out_h = (p.out.size() >= 3 && p.out.size() < 5) ? p.out[2] : (p.out.size() == 5) ? p.out[3] : 1; - int out_w = (p.out.size() >= 4 && p.out.size() < 5) ? p.out[3] : (p.out.size() == 5) ? p.out[4] : 1; - - int hot_axis = (p.axis == - 1) ? p.in.size() : p.axis; - - for (int ob = 0; ob < out_n; ob++) { - for (int oc = 0; oc < out_c; oc++) { - for (int od = 0; od < out_d; od++) { - for (int oh = 0; oh < out_h; oh++) { - for (int ow = 0; ow < out_w; ow++) { - std::size_t dst_offset = ow + out_w * oh + out_w * out_h * od + out_w * out_h * out_d * oc + out_w * out_h * out_d * out_c * ob; - std::size_t src_offset = 0; - - std::vector out_dims = {ob, oc, oh, ow}; - if (p.out.size() == 5) - out_dims.insert(out_dims.begin() + 2, od); - std::vector in_dims(out_dims.begin(), out_dims.end()); - in_dims.erase(in_dims.begin() + hot_axis); - - for (int i = 0; i < p.in.size(); i++) { - int mul = 1; - if (i == p.in.size() - 1) { - src_offset += in_dims[i]; - break; - } - for (int j = i; j < p.in.size(); j++) { - if (j == i) - mul *= in_dims[j]; - else - mul *= p.in[j]; - } - src_offset += mul; - } - - if (out_dims[hot_axis] == src_ptr[src_offset]) - dst_ptr[dst_offset] = p.on; - else - dst_ptr[dst_offset] = p.off; - } - } - } - } - } - } -protected: - virtual void SetUp() { - try { - TestsCommon::SetUp(); - one_hot_test_params p = ::testing::WithParamInterface::GetParam(); - std::string model = getModel(p); - - Core ie; - CNNNetwork net = ie.ReadNetwork(model, Blob::CPtr()); - ExecutableNetwork executable_network = ie.LoadNetwork(net, p.device_name); - InferRequest inferRequest = executable_network.CreateInferRequest(); - - // Output Data - OutputsDataMap out = net.getOutputsInfo(); - std::pair item = *out.begin(); - - TBlob::Ptr output; - output = make_shared_blob(item.second->getTensorDesc()); - output->allocate(); - inferRequest.SetBlob(item.first, output); - - // Output Reference - TBlob dst_ref(item.second->getTensorDesc()); - dst_ref.allocate(); - - Blob::Ptr src; - src = make_shared_blob({ Precision::FP32, p.in, TensorDesc::getLayoutByDims(p.in) }); - src->allocate(); - float* s = src->buffer().as(); - for (int i = 0; i < src->size(); ++i) - s[i] = -1; - s[0] = 1; - s[1] = 1; - inferRequest.SetBlob("input", src); - - inferRequest.Infer(); - - // Check results - ref_one_hot_4d(*src, dst_ref, p); - - compare(*output, dst_ref); - } catch (const Exception &e) { - FAIL() << e.what(); - } - } -}; - -#define case_2d_0 one_hot_base_params({{3}, {3, 6},-1, 6, 1.0f, 0.0f }) -#define case_2d_1 one_hot_base_params({{3}, {6, 3}, 0, 6, 1.0f, 0.0f }) -#define case_2d_2 one_hot_base_params({{3}, {3, 6}, 1, 6, 1.0f, 0.0f }) -#define case_3d_0 one_hot_base_params({{3, 2}, {3, 2, 4},-1, 4, 1.0f, 0.0f }) -#define case_3d_1 one_hot_base_params({{3, 2}, {4, 3, 2}, 0, 4, 1.0f, 0.0f }) -#define case_3d_2 one_hot_base_params({{3, 2}, {3, 4, 2}, 1, 4, 1.0f, 0.0f }) -#define case_4d_0 one_hot_base_params({ {1, 3, 2}, {1, 3, 2, 4},-1, 4, 1.0f, 0.0f }) -#define case_4d_1 one_hot_base_params({ {1, 3, 2}, {4, 1, 3, 2}, 0, 4, 1.0f, 0.0f }) -#define case_4d_2 one_hot_base_params({ {1, 3, 2}, {1, 4, 3, 2}, 1, 4, 1.0f, 0.0f }) -#define case_4d_3 one_hot_base_params({ {1, 3, 2}, {1, 3, 4, 2}, 2, 4, 1.0f, 0.0f }) -#define case_5d_0 one_hot_base_params({ {1, 3, 2, 3}, {4, 1, 3, 2, 3}, 0, 4, 1.0f, 0.0f }) -#define case_5d_1 one_hot_base_params({ {1, 3, 2, 3}, {1, 4, 3, 2, 3}, 1, 4, 1.0f, 0.0f }) -#define case_5d_2 one_hot_base_params({ {1, 3, 2, 3}, {1, 3, 4, 2, 3}, 2, 4, 1.0f, 0.0f }) -#define case_5d_3 one_hot_base_params({ {1, 3, 2, 3}, {1, 3, 2, 4, 3}, 3, 4, 1.0f, 0.0f }) -#define case_5d_4 one_hot_base_params({ {1, 3, 2, 3}, {1, 3, 2, 3, 4}, 4, 4, 1.0f, 0.0f }) - -TEST_P(OneHotOnlyTestShared, TestsOneHot) {} diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/permute_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/permute_tests.hpp deleted file mode 100644 index 361a6f29f46..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/permute_tests.hpp +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include - -#include "tests_common.hpp" -#include "single_layer_common.hpp" - -using namespace ::testing; -using namespace InferenceEngine; -using namespace std; - - -struct permute_base_params { - SizeVector dims; - SizeVector order; -}; - -struct permute_test_params { - std::string device_name; - permute_base_params base; - permute_test_params(std::string name, permute_base_params params) : device_name(name), base(params) {} -}; - -template -void ref_permute(const TBlob &src, TBlob &dst, permute_base_params prm) { - const data_t *src_data = src.readOnly(); - data_t *dst_data = dst.data(); - - SizeVector orderedDims; - for (auto ord : prm.order) { - orderedDims.push_back(src.getTensorDesc().getDims()[ord]); - } - TensorDesc desc(Precision::FP32, src.getTensorDesc().getDims(), {orderedDims, prm.order}); - - for (int i=0; i < src.size(); i++) { - dst_data[desc.offset(i)] = src_data[src.getTensorDesc().offset(i)]; - } -} - -class PermuteOnlyTests: public TestsCommon, - public WithParamInterface { - std::string model_t = R"V0G0N( - - - - - - __DIMS__ - - - - - - - - __DIMS__ - - - - - __DST_DIMS__ - - - - - - - - -)V0G0N"; - -protected: - std::string getModel(permute_base_params p) { - std::string model = model_t; - std::string dims; - std::string dst_dims; - for (auto& dim : p.dims) { - dims += ""; - dims += std::to_string(dim) + "\n"; - } - - std::string order; - for (auto& ord : p.order) { - if (!order.empty()) - order += ","; - order += std::to_string(ord); - dst_dims += ""; - dst_dims += std::to_string(p.dims[ord]) + "\n"; - } - - REPLACE_WITH_STR(model, "__DIMS__", dims); - REPLACE_WITH_STR(model, "__DST_DIMS__", dst_dims); - REPLACE_WITH_STR(model, "_ORDER_", order); - - return model; - } - - virtual void TearDown() { - } - - virtual void SetUp() { - try { - TestsCommon::SetUp(); - permute_test_params p = ::testing::WithParamInterface::GetParam(); - std::string model = getModel(p.base); - - Core ie; - CNNNetwork net = ie.ReadNetwork(model, Blob::CPtr()); - ExecutableNetwork executable_network = ie.LoadNetwork(net, p.device_name); - InferRequest inferRequest = executable_network.CreateInferRequest(); - - Blob::Ptr src = make_shared_blob({Precision::FP32, p.base.dims, - TensorDesc::getLayoutByDims(p.base.dims)}); - src->allocate(); - fill_data(src->buffer(), src->size()); - - auto* srcPtr = dynamic_cast*>(src.get()); - - if (srcPtr == nullptr) - FAIL() << "Cannot cast blob to TBlob."; - - inferRequest.SetBlob("in1", src); - - OutputsDataMap out = net.getOutputsInfo(); - auto item = *out.begin(); - - TBlob::Ptr output; - output = make_shared_blob(item.second->getTensorDesc()); - output->allocate(); - inferRequest.SetBlob(item.first, output); - inferRequest.Infer(); - - TensorDesc td(Precision::FP32, p.base.dims, - TensorDesc::getLayoutByDims(p.base.dims)); - TBlob dst_ref(td); - dst_ref.allocate(); - - ref_permute(*srcPtr, dst_ref, p.base); - - compare(*output, dst_ref); - } catch (const Exception &e) { - FAIL() << e.what(); - } - } -}; - -TEST_P(PermuteOnlyTests, TestsPermute) {} - -#define case_1 permute_base_params{{2, 3, 4, 5}, {0, 1, 2, 3}} -#define case_2 permute_base_params{{2, 3, 4, 5}, {0, 2, 3, 1}} -#define case_3 permute_base_params{{2, 3, 4, 5}, {0, 2, 1, 3}} -#define case_4 permute_base_params{{2, 3, 4}, {0, 1, 2}} -#define case_5 permute_base_params{{2, 3, 4}, {0, 2, 1}} -#define case_6 permute_base_params{{2, 3}, {0, 1}} -#define case_7 permute_base_params{{2, 3, 4, 5, 6}, {0, 1, 2, 3, 4}} -#define case_8 permute_base_params{{2, 3, 4, 5, 6}, {0, 4, 2, 1, 3}} -#define case_9 permute_base_params{{2, 3, 4, 5, 6}, {0, 2, 4, 3, 1}} -#define case_10 permute_base_params{{2, 3, 4, 5, 6}, {0, 3, 2, 4, 1}} -#define case_11 permute_base_params{{2, 8, 2, 2, 4, 5}, {0, 1, 4, 2, 5, 3}} -#define case_12 permute_base_params{{2, 8, 3, 3, 4, 5}, {0, 1, 4, 2, 5, 3}} -#define case_13 permute_base_params{{2, 12, 9}, {0, 2, 1}} -#define case_14 permute_base_params{{2, 8, 3, 3, 4, 5}, {0, 3, 4, 1, 5, 2}} -#define case_15 permute_base_params{{2, 3, 4, 5}, {0, 1, 3, 2}} -#define case_16 permute_base_params{{2, 3, 4, 5, 7}, {0, 3, 1, 4, 2}} diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/quantize_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/quantize_tests.hpp deleted file mode 100644 index 23fcd962a75..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/quantize_tests.hpp +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include "cpp_interfaces/interface/ie_internal_plugin_config.hpp" - -#include "tests_common.hpp" -#include "single_layer_common.hpp" -#include "common_test_utils/data_utils.hpp" - -using namespace ::testing; -using namespace InferenceEngine; - -struct quantize_test_params { - std::string device_name; - - struct { - size_t n; - size_t c; - size_t h; - size_t w; - } in; - - size_t ic_const_blobs; - size_t levels; - bool reverse_out_vals; -}; - -template -void ref_quantize(const std::vector &srcs, std::vector &dsts, quantize_test_params prm) { - assert(dsts.size() == 1); - - const data_t* src_data = srcs[0]->buffer().as(); - const data_t* input_low_data = srcs[1]->buffer().as(); - const data_t* input_high_data = srcs[2]->buffer().as(); - const data_t* output_low_data = srcs[3]->buffer().as(); - const data_t* output_high_data = srcs[4]->buffer().as(); - - data_t* dst_data = dsts[0]->buffer().as(); - - size_t N = prm.in.n; - size_t C = prm.in.c; - size_t H = prm.in.h; - size_t W = prm.in.w; - size_t ICB = prm.ic_const_blobs; - - for (size_t n = 0; n < N; n++) { - for (size_t c = 0; c < C; c++) { - for (size_t h = 0; h < H; h++) { - for (size_t w = 0; w < W; w++) { - size_t idx = n*C*H*W + c*H*W + h*W + w; - - if (src_data[idx] <= input_low_data[c % ICB]) - dst_data[idx] = output_low_data[c % ICB]; - else if (src_data[idx] > input_high_data[c % ICB]) - dst_data[idx] = output_high_data[c % ICB]; - else - dst_data[idx] = roundf((src_data[idx] - input_low_data[c % ICB]) / - (input_high_data[c % ICB] - input_low_data[c % ICB]) * (prm.levels-1)) / - (prm.levels-1) * (output_high_data[c % ICB] - output_low_data[c % ICB]) + output_low_data[c % ICB]; - } - } - } - } -} - -class QuantizeOnlyTest : public TestsCommon, public WithParamInterface { - - std::string model_t = R"V0G0N( - - - - - - _IN_ - _IC_ - _IH_ - _IW_ - - - - - - - 1 - _ICB_ - 1 - 1 - - - - - - - - - - 1 - _ICB_ - 1 - 1 - - - - - - - - - - 1 - _ICB_ - 1 - 1 - - - - - - - - - - 1 - _ICB_ - 1 - 1 - - - - - - - - - - - _IN_ - _IC_ - _IH_ - _IW_ - - - 1 - _ICB_ - 1 - 1 - - - 1 - _ICB_ - 1 - 1 - - - 1 - _ICB_ - 1 - 1 - - - 1 - _ICB_ - 1 - 1 - - - - - _IN_ - _IC_ - _IH_ - _IW_ - - - - - - - - - - - - -)V0G0N"; - - std::string getModel(quantize_test_params p) { - std::string model = model_t; - - REPLACE_WITH_NUM(model, "_IN_", p.in.n); - REPLACE_WITH_NUM(model, "_IC_", p.in.c); - REPLACE_WITH_NUM(model, "_IH_", p.in.h); - REPLACE_WITH_NUM(model, "_IW_", p.in.w); - REPLACE_WITH_NUM(model, "_L_", p.levels); - REPLACE_WITH_NUM(model, "_ICB_", p.ic_const_blobs); - - REPLACE_WITH_NUM(model, "_O1_", 0 * p.ic_const_blobs * sizeof(float)); - REPLACE_WITH_NUM(model, "_S1_", 1 * p.ic_const_blobs * sizeof(float)); - REPLACE_WITH_NUM(model, "_O2_", 1 * p.ic_const_blobs * sizeof(float)); - REPLACE_WITH_NUM(model, "_S2_", 1 * p.ic_const_blobs * sizeof(float)); - REPLACE_WITH_NUM(model, "_O3_", 2 * p.ic_const_blobs * sizeof(float)); - REPLACE_WITH_NUM(model, "_S3_", 1 * p.ic_const_blobs * sizeof(float)); - REPLACE_WITH_NUM(model, "_O4_", 3 * p.ic_const_blobs * sizeof(float)); - REPLACE_WITH_NUM(model, "_S4_", 1 * p.ic_const_blobs * sizeof(float)); - - return model; - } - -protected: - virtual void SetUp() { - - try { - quantize_test_params p = ::testing::WithParamInterface::GetParam(); - std::string model = getModel(p); - - std::vector srcs_vec; - Blob::Ptr blob_data = make_shared_blob({Precision::FP32, {p.in.n, p.in.c, p.in.h, p.in.w}, Layout::NCHW}); - blob_data->allocate(); - CommonTestUtils::fill_data_sine(blob_data->buffer().as(), blob_data->size(), 0.f, 2.f, 0.1f); - srcs_vec.push_back(blob_data); - - float low_center = p.levels == 2 ? 0.f : -1.f; - float high_center = p.levels == 2 ? 0.f : 1.f; - float low_val = p.reverse_out_vals ? 1.0f : -1.f; - float high_val = p.reverse_out_vals ? -1.0f : 1.f; - - Blob::Ptr input_low_data = make_shared_blob({Precision::FP32, {p.ic_const_blobs}, Layout::C}); - input_low_data->allocate(); - CommonTestUtils::fill_data_sine(input_low_data->buffer().as(), input_low_data->size(), low_center, 2.f, 0.2f); - srcs_vec.push_back(input_low_data); - - Blob::Ptr input_high_data = make_shared_blob({Precision::FP32, {p.ic_const_blobs}, Layout::C}); - input_high_data->allocate(); - CommonTestUtils::fill_data_sine(input_high_data->buffer().as(), input_high_data->size(), high_center, 2.f, 0.2f); - srcs_vec.push_back(input_high_data); - - Blob::Ptr output_low_data = make_shared_blob({Precision::FP32, { p.ic_const_blobs }, Layout::C}); - output_low_data->allocate(); - if (p.levels == 2) { - CommonTestUtils::fill_data_const(output_low_data, low_val); - } else { - CommonTestUtils::fill_data_sine(output_low_data->buffer().as(), output_low_data->size(), low_center, 2.f, 0.3f); - }; - srcs_vec.push_back(output_low_data); - - Blob::Ptr output_high_data = make_shared_blob({Precision::FP32, {p.ic_const_blobs}, Layout::C}); - output_high_data->allocate(); - if (p.levels == 2) { - CommonTestUtils::fill_data_const(output_high_data, high_val); - } else { - CommonTestUtils::fill_data_sine(output_high_data->buffer().as(), output_high_data->size(), high_center, 2.f, 0.3f); - }; - srcs_vec.push_back(output_high_data); - - TBlob *weights_ptr = new TBlob({Precision::U8, {4 * p.ic_const_blobs * sizeof(float)}, Layout::C}); - weights_ptr->allocate(); - - float* pwei = weights_ptr->buffer().as(); - int off = 0; - for (int i = 1; i < 5; i++) { - float* pdata = srcs_vec[i]->buffer(); - for (int j = 0; j < p.ic_const_blobs; j++) { - pwei[off++] = pdata[j]; - } - } - - Core ie; - CNNNetwork net = ie.ReadNetwork(model, TBlob::Ptr(weights_ptr)); - - std::map config = {{PluginConfigInternalParams::KEY_LP_TRANSFORMS_MODE, PluginConfigParams::NO}}; - ExecutableNetwork executable_network = ie.LoadNetwork(net, p.device_name, config); - InferRequest inferRequest = executable_network.CreateInferRequest(); - inferRequest.SetBlob("data", blob_data); - - std::vector dsts_vec; - std::vector out_vec; - - OutputsDataMap out_info_map = net.getOutputsInfo(); - for (auto info : out_info_map) { - Blob::Ptr blob = make_shared_blob({Precision::FP32, info.second->getDims() , Layout::NCHW}); - blob->allocate(); - inferRequest.SetBlob(info.first, blob); - out_vec.push_back(blob); - - Blob::Ptr blob_ref = make_shared_blob({Precision::FP32, info.second->getDims(), Layout::NCHW}); - blob_ref->allocate(); - dsts_vec.push_back(blob_ref); - } - - ref_quantize(srcs_vec, dsts_vec, p); - - inferRequest.Infer(); - - compare(*out_vec[0], *dsts_vec[0]); - - } catch (const InferenceEngine::Exception &e) { - FAIL() << e.what(); - } - } -}; - -// {N, C, H, W}, ic_const_blobs, quantization_levels, reverse_out_vals -#define case_1 {1, 8, 5, 5}, 1, 2, false -#define case_2 {1, 8, 5, 5}, 8, 2, false -#define case_3 {1, 8, 5, 5}, 1, 4, false -#define case_4 {1, 8, 5, 5}, 8, 4, false -#define case_5 {1, 8, 5, 4}, 1, 8, false -#define case_6 {1, 8, 5, 4}, 8, 8, false -#define case_7 {1, 17, 5, 5}, 1, 2, false -#define case_8 {1, 17, 5, 5}, 17, 2, false -#define case_9 {1, 17, 5, 5}, 1, 4, false -#define case_10 {1, 17, 5, 5}, 17, 4, false -#define case_11 {1, 17, 5, 4}, 1, 8, false -#define case_12 {1, 17, 5, 4}, 17, 8, false -#define case_13 {1, 8, 5, 5}, 1, 2, true -#define case_14 {1, 8, 5, 5}, 8, 2, true -#define case_15 {1, 8, 5, 5}, 1, 4, true -#define case_16 {1, 8, 5, 5}, 8, 4, true -#define case_17 {1, 8, 5, 4}, 1, 8, true -#define case_18 {1, 8, 5, 4}, 8, 8, true -#define case_19 {1, 17, 5, 5}, 1, 2, true -#define case_20 {1, 17, 5, 5}, 17, 2, true -#define case_21 {1, 17, 5, 5}, 1, 4, true -#define case_22 {1, 17, 5, 5}, 17, 4, true -#define case_23 {1, 17, 5, 4}, 1, 8, true -#define case_24 {1, 17, 5, 4}, 17, 8, true - -TEST_P(QuantizeOnlyTest, TestsQuantize) {} diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/reduce_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/reduce_tests.hpp deleted file mode 100644 index 63a6eded90b..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/reduce_tests.hpp +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include - -#include "tests_common.hpp" -#include "single_layer_common.hpp" -#include "ie_memcpy.h" - -using namespace ::testing; -using namespace InferenceEngine; -using namespace std; - -struct reduce_test_params { - std::string device_name; - std::string inIdxPrecision;; - std::string reduce_type; - bool keep_dims; - SizeVector in_shape; - std::vector input_tensor; - std::vector axes_for_reduction; - SizeVector out_shape; - std::vector reference; -}; - -template -void reduce( - const float* src_data, - SizeVector src_dims, - SizeVector srcStrides, - float* dst_data, - SizeVector dst_dims, - SizeVector dstStrides, - float init_value, - bool keep_dims, - SizeVector skip_dims, - F func -) { - size_t i, src_idx, dst_idx; - for (i = 0; i < dstStrides[0] * dst_dims[0]; ++i) - dst_data[i] = init_value; - - SizeVector counters(src_dims.size(), 0); - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) { - if (keep_dims) - for (i = 0, dst_idx = 0; i < dst_dims.size(); ++i) - dst_idx += (counters[i] % dst_dims[i]) * dstStrides[i]; - else - for (i = 0, dst_idx = 0; i < dst_dims.size(); ++i) - dst_idx += counters[skip_dims[i]] * dstStrides[i]; - - dst_data[dst_idx] = func(dst_data[dst_idx], src_data[src_idx]); - for (int j = src_dims.size() - 1; j >= 0; j--) { - counters[j] = (counters[j] + 1) % src_dims[j]; - if (counters[j] != 0) break; - } - } -} - -void ref_reduce( - std::string reduce_type, - TBlob &src, - bool keep_dims, - std::vector axes_for_reduction, - TBlob &dst, - SizeVector &out_dims -) { - size_t i, src_idx, dst_idx; - const float* src_data = src.data(); - SizeVector src_dims = src.getTensorDesc().getDims(); - SizeVector srcStrides = src.getTensorDesc().getBlockingDesc().getStrides(); - float* dst_data = dst.data(); - SizeVector dst_dims = dst.getTensorDesc().getDims(); - SizeVector dstStrides = dst.getTensorDesc().getBlockingDesc().getStrides(); - SizeVector skip_dims; - - if (!dst_dims.size()) - dst_dims = InferenceEngine::SizeVector(1, 1); - - if (!dstStrides.size()) - dstStrides = InferenceEngine::SizeVector(1, 1); - - if (axes_for_reduction.size() == 0) - FAIL() << " Index vector should be 1 dimension"; - - for (i = 0; i < axes_for_reduction.size(); i++) { - int32_t axis = axes_for_reduction[i]; - if (axis < 0) - axis += src_dims.size(); - - if (axis > src_dims.size()) - FAIL() << " Index to squeeze exceeds data tensor dimension"; - axes_for_reduction[i] = axis; - } - - for (size_t j = 0; j < src_dims.size(); j++) { - bool found = false; - for (size_t axis : axes_for_reduction) - if (j == axis) found = true; - - if (!found) { - out_dims.push_back(src_dims[j]); - if (!keep_dims) skip_dims.push_back(j); - } - else { - if (keep_dims) out_dims.push_back(1); - } - } - - if (reduce_type == "ReduceAnd") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 1.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x && y; } ); - } else { - dst_data[0] = 1.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] = dst_data[0] && src_data[src_idx]; - } - } else if (reduce_type == "ReduceL1") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 0.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x + (std::abs)(y); } ); - } else { - dst_data[0] = 0.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] += (std::abs)(src_data[src_idx]); - } - } else if (reduce_type == "ReduceL2") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 0.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x + y * y; } ); - - for (i = 0; i < dstStrides[0] * dst_dims[0]; ++i) - dst_data[i] = (std::sqrt)(dst_data[i]); - } else { - dst_data[0] = 0.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] += src_data[src_idx] * src_data[src_idx]; - dst_data[0] = sqrt(dst_data[0]); - } - } else if (reduce_type == "ReduceLogSum") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 0.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x + y; }); - - for (i = 0; i < dstStrides[0] * dst_dims[0]; ++i) - dst_data[i] = logf(dst_data[i]); - } else { - dst_data[0] = 0.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] += src_data[src_idx]; - dst_data[0] = logf(dst_data[0]); - } - } else if (reduce_type == "ReduceLogSumExp") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 0.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x + expf(y); }); - - for (i = 0; i < dstStrides[0] * dst_dims[0]; ++i) - dst_data[i] = logf(dst_data[i]); - } else { - dst_data[0] = 0.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] += expf(src_data[src_idx]); - dst_data[0] = logf(dst_data[0]); - } - } else if (reduce_type == "ReduceMax") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, FLT_MIN, keep_dims, skip_dims, - [](float x, float y)->float { return x > y ? x : y; }); - } else { - dst_data[0] = FLT_MIN; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] = dst_data[0] > src_data[src_idx] ? dst_data[0] : src_data[src_idx]; - } - } else if (reduce_type == "ReduceMean") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 0.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x + y; }); - float reduced_dims_work_amount = 1.f; - for (size_t axis : axes_for_reduction) { - reduced_dims_work_amount *= static_cast(src_dims[axis]); - } - for (i = 0; i < dstStrides[0] * dst_dims[0]; ++i) - dst_data[i] /= reduced_dims_work_amount; - } else { - dst_data[0] = 0.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] += src_data[src_idx]; - dst_data[0] /= static_cast(srcStrides[0] * src_dims[0]); - } - } else if (reduce_type == "ReduceMin") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, FLT_MAX, keep_dims, skip_dims, - [](float x, float y)->float { return x < y ? x : y; }); - } else { - dst_data[0] = FLT_MAX; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] = dst_data[0] < src_data[src_idx] ? dst_data[0] : src_data[src_idx]; - } - } else if (reduce_type == "ReduceOr") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 0.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x || y; }); - } else { - dst_data[0] = 0; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] = dst_data[0] || src_data[src_idx]; - } - } else if (reduce_type == "ReduceProd") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 1.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x * y; }); - } else { - dst_data[0] = 1.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] *= src_data[src_idx]; - } - } else if (reduce_type == "ReduceSum") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 0.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x + y; }); - } else { - dst_data[0] = 0.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] += src_data[src_idx]; - } - } else if (reduce_type == "ReduceSumSquare") { - if (out_dims.size()) { - reduce(src_data, src_dims, srcStrides, dst_data, dst_dims, dstStrides, 0.0f, keep_dims, skip_dims, - [](float x, float y)->float { return x + y * y; }); - } else { - dst_data[0] = 0.0f; - for (src_idx = 0; src_idx < srcStrides[0] * src_dims[0]; ++src_idx) - dst_data[0] += src_data[src_idx] * src_data[src_idx]; - } - } -} - -class ReduceTestsShared : public TestsCommon, public WithParamInterface { - std::string model_t = R"V0G0N( - - - - - - _IN_ - - - - - - - _DIM_SIZE_ - - - - - - - - - - - _IN_ - - - _DIM_SIZE_ - - - - - _OUT_ - - - - - - - - - -)V0G0N"; - - std::string getModel(reduce_test_params p) { - std::string model = model_t; - std::string in_shape; - std::string out_shape = ""; - - for (size_t i = 0; i < p.in_shape.size(); i++) { - in_shape += ""; - in_shape += std::to_string(p.in_shape[i]) + "\n"; - } - REPLACE_WITH_STR(model, "_IN_", in_shape); - REPLACE_WITH_NUM(model, "_DIM_SIZE_", p.axes_for_reduction.size()); - REPLACE_WITH_STR(model, "_REDUCE_TYPE_", p.reduce_type); - REPLACE_WITH_STR(model, "_IIDXP_", p.inIdxPrecision); - REPLACE_WITH_NUM(model, "_KEEP_DIMS_", p.keep_dims); - - for (size_t i = 0; i < p.out_shape.size(); i++) { - out_shape += ""; - out_shape += std::to_string(p.out_shape[i]) + "\n"; - } - REPLACE_WITH_STR(model, "_OUT_", out_shape); - - return model; - } - -protected: - virtual void TearDown() { - } - - static void fill_data_dbgval(float* data, size_t size) { - for (size_t i = 0; i < size; i++) { - data[i] = i + 1; - } - } - - virtual void SetUp() { - try { - TestsCommon::SetUp(); - reduce_test_params p = ::testing::WithParamInterface::GetParam(); - std::string model = getModel(p); - - // std::cout << model << std::endl; - - TBlob * axes = nullptr; - if (p.inIdxPrecision == "I32") { - axes = new TBlob({Precision::U8, - {p.axes_for_reduction.size() * sizeof(int32_t)}, - Layout::C}); - axes->allocate(); - for (size_t i = 0; i < p.axes_for_reduction.size(); i++) { - ((int32_t *) axes->buffer())[i] = p.axes_for_reduction[i]; - } - } else { - axes = new TBlob({Precision::U8, - { p.axes_for_reduction.size() * sizeof(float) }, - Layout::C}); - axes->allocate(); - for (size_t i = 0; i < p.axes_for_reduction.size(); i++) { - ((float *) axes->buffer())[i] = p.axes_for_reduction[i]; - } - } - - Core ie; - auto net = ie.ReadNetwork(model, TBlob::Ptr(axes)); - OutputsDataMap out = net.getOutputsInfo(); - std::pair item = *out.begin(); - - ExecutableNetwork executable_network = ie.LoadNetwork(net, p.device_name); - InferRequest inferRequest = executable_network.CreateInferRequest(); - - // Input Data - Blob::Ptr src; - src = make_shared_blob({ Precision::FP32, p.in_shape, TensorDesc::getLayoutByDims(p.in_shape) }); - src->allocate(); - if(p.input_tensor.size()) - ie_memcpy(src->buffer(), src->byteSize(), &p.input_tensor[0], sizeof(float)*p.input_tensor.size()); - else - fill_data_dbgval(src->buffer(), src->size()); - - auto* srcPtr = dynamic_cast*>(src.get()); - if (srcPtr == nullptr) - FAIL() << "Cannot cast blob to TBlob."; - - // Output Reference - TBlob dst_ref(item.second->getTensorDesc()); - dst_ref.allocate(); - - SizeVector out_dims; - ref_reduce(p.reduce_type, *srcPtr, p.keep_dims, p.axes_for_reduction, dst_ref, out_dims); - if (p.out_shape.size()>0 && out_dims.size() != p.out_shape.size()) - FAIL() << "Wrong out_shape size!"; - for (size_t i = 0; i < p.out_shape.size(); i++) { - if (out_dims[i] != p.out_shape[i]) - FAIL() << "Wrong out_shape dimensions!"; - } - if (p.reference.size()) - if (memcmp(dst_ref.data(), &p.reference[0], p.reference.size() * sizeof(float)) != 0) - FAIL() << "Wrong result with compare reference vector!"; - - // Output Data - auto output = make_shared_blob(item.second->getTensorDesc()); - output->allocate(); - inferRequest.SetBlob(item.first, output); - - // Input - inferRequest.SetBlob("input", src); - inferRequest.Infer(); - - compare(*output, dst_ref); - } catch (const Exception &e) { - FAIL() << e.what(); - } - } -}; - -TEST_P(ReduceTestsShared, SharedReduceTests) {} diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/resample_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/resample_tests.hpp deleted file mode 100644 index 2e9b53a3fab..00000000000 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/resample_tests.hpp +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include - -#include "tests_common.hpp" -#include "single_layer_common.hpp" - -using namespace ::testing; -using namespace InferenceEngine; -using namespace std; - -struct resample_test_params { - std::string device_name; - InferenceEngine::SizeVector in_dims; - float factor; - std::string type; -}; - -static inline float triangleCoeff(float x) { - return std::max(0.0f, 1 - std::abs(x)); -} - -template -static void ref_resample(const InferenceEngine::TBlob &src, InferenceEngine::TBlob &dst, resample_test_params p) { - const data_t *src_data = src.readOnly(); - data_t *dst_data = dst.data(); - - size_t ndims = p.in_dims.size(); - - size_t N = p.in_dims[0]; - size_t C = p.in_dims[1]; - size_t ID = ndims == 5 ? p.in_dims[ndims - 3] : 1; - size_t IH = p.in_dims[ndims - 2]; - size_t IW = p.in_dims[ndims - 1]; - size_t OD = ndims == 5 ? static_cast(ID / p.factor) : 1; - size_t OH = static_cast(IH / p.factor); - size_t OW = static_cast(IW / p.factor); - - float fx = static_cast(IW) / static_cast(OW); - float fy = static_cast(IH) / static_cast(OH); - float fz = static_cast(ID) / static_cast(OD); - - if (p.type == "caffe.ResampleParameter.NEAREST") { - for (size_t b = 0; b < N; b++) { - for (size_t c = 0; c < C; c++) { - const float* in_ptr = src_data + IW * IH * ID * C * b + IW * IH * ID * c; - float* out_ptr = dst_data + OW * OH * OD * C * b + OW * OH * OD * c; - for (size_t oz = 0; oz < OD; oz++) { - for (size_t oy = 0; oy < OH; oy++) { - for (size_t ox = 0; ox < OW; ox++) { - float ix = ox * fx; - float iy = oy * fy; - float iz = oz * fz; - - size_t ix_r = static_cast(std::floor(ix)); - size_t iy_r = static_cast(std::floor(iy)); - size_t iz_r = static_cast(std::floor(iz)); - - out_ptr[oz * OH * OW + oy * OW + ox] = in_ptr[iz_r * IH * IW + iy_r * IW + ix_r]; - } - } - } - } - } - } else if (p.type == "caffe.ResampleParameter.LINEAR") { - size_t kernel_width = 2; - bool isDownsample = (fx > 1) || (fy > 1) || (fz > 1); - bool antialias = false; - - for (size_t b = 0; b < N; b++) { - for (size_t c = 0; c < C; c++) { - const float* in_ptr = src_data + IW * IH * ID * C * b + IW * IH * ID * c; - float* out_ptr = dst_data + OW * OH * OD * C * b + OW * OH * OD * c; - - for (size_t oz = 0; oz < OD; oz++) { - for (size_t oy = 0; oy < OH; oy++) { - for (size_t ox = 0; ox < OW; ox++) { - float ix = ox * fx + fy / 2.0f - 0.5f; - float iy = oy * fy + fx / 2.0f - 0.5f; - float iz = oz * fz + fz / 2.0f - 0.5f; - - int ix_r = static_cast(round(ix)); - int iy_r = static_cast(round(iy)); - int iz_r = static_cast(round(iz)); - - float sum = 0; - float wsum = 0; - - float ax = 1.0f / (antialias ? fx : 1.0f); - float ay = 1.0f / (antialias ? fy : 1.0f); - float az = 1.0f / (antialias ? fz : 1.0f); - - int rx = (fx < 1.0f) ? 2 : static_cast(ceil(static_cast(kernel_width) / ax)); - int ry = (fy < 1.0f) ? 2 : static_cast(ceil(static_cast(kernel_width) / ay)); - int rz = (fz < 1.0f) ? 2 : static_cast(ceil(static_cast(kernel_width) / az)); - - for (int z = iz_r - rz; z <= iz_r + rz; z++) { - for (int y = iy_r - ry; y <= iy_r + ry; y++) { - for (int x = ix_r - rx; x <= ix_r + rx; x++) { - if (z < 0 || y < 0 || x < 0 || z >= static_cast(ID) || y >= static_cast(IH) || x >= static_cast(IW)) - continue; - - float dx = ix - x; - float dy = iy - y; - float dz = iz - z; - - float w = ax * triangleCoeff(ax * dx) * ay * triangleCoeff(ay * dy) * az * triangleCoeff(az * dz); - - sum += w * in_ptr[z * IH * IW + y * IW + x]; - wsum += w; - } - } - } - out_ptr[oz * OH * OW + oy * OW + ox] = (!wsum) ? 0 : (sum / wsum); - } - } - } - } - } - } else { - assert(!"Unsupported resample operation type"); - } -} - -class ResampleTests : public TestsCommon, public WithParamInterface { - std::string model_t = R"V0G0N( - - - - - - _IN_ - _IC_ - _ID_ - _IH_ - _IW_ - - - - - - - - _IN_ - _IC_ - _ID_ - _IH_ - _IW_ - - - - - _IN_ - _IC_ - _OD_ - _OH_ - _OW_ - - - - - - - - -)V0G0N"; - - std::string getModel(resample_test_params p) { - std::string model = model_t; - std::string inDim; - - auto dims_size = p.in_dims.size(); - if (dims_size == 4) { - REMOVE_LINE(model, "_ID_"); - REMOVE_LINE(model, "_OD_"); - } - - REPLACE_WITH_NUM(model, "_IN_", p.in_dims[0]); - REPLACE_WITH_NUM(model, "_IC_", p.in_dims[1]); - if (dims_size == 5) - REPLACE_WITH_NUM(model, "_ID_", p.in_dims[dims_size - 3]); - REPLACE_WITH_NUM(model, "_IH_", p.in_dims[dims_size - 2]); - REPLACE_WITH_NUM(model, "_IW_", p.in_dims[dims_size - 1]); - - if (dims_size == 5) - REPLACE_WITH_NUM(model, "_OD_", (int)(p.in_dims[dims_size - 3] / p.factor)); - REPLACE_WITH_NUM(model, "_OH_", (int)(p.in_dims[dims_size - 2] / p.factor)); - REPLACE_WITH_NUM(model, "_OW_", (int)(p.in_dims[dims_size - 1] / p.factor)); - - REPLACE_WITH_NUM(model, "_AN_", 0); - REPLACE_WITH_NUM(model, "_F_", p.factor); - REPLACE_WITH_STR(model, "_T_", p.type); - - return model; - } - -protected: - virtual void TearDown() { - } - - virtual void SetUp() { - try { - TestsCommon::SetUp(); - resample_test_params p = ::testing::WithParamInterface::GetParam(); - std::string model = getModel(p); - - Core ie; - CNNNetwork net = ie.ReadNetwork(model, Blob::CPtr()); - InputsDataMap in_info_map = net.getInputsInfo(); - OutputsDataMap out_info_map = net.getOutputsInfo(); - - ExecutableNetwork executable_network = ie.LoadNetwork(net, p.device_name); - InferRequest inferRequest = executable_network.CreateInferRequest(); - - InferenceEngine::Layout layout = InferenceEngine::ANY; - switch (p.in_dims.size()) { - case 4: layout = InferenceEngine::NCHW; break; - case 5: layout = InferenceEngine::NCDHW; break; - default: - FAIL() << "Input dims size not supported in this test."; - } - - InferenceEngine::Blob::Ptr src = InferenceEngine::make_shared_blob({InferenceEngine::Precision::FP32, p.in_dims, layout}); - src->allocate(); - fill_data(src->buffer(), src->size()); - for (size_t i = 0; i < src->size(); i++) { - src->buffer().as()[i] = static_cast(i); - } - - auto * srcPtr = dynamic_cast*>(src.get()); - - if (srcPtr == nullptr) - FAIL() << "Cannot cast blob to TBlob."; - - InferenceEngine::BlobMap srcs; - srcs.insert(std::pair("input", src)); - - InferenceEngine::OutputsDataMap out; - out = net.getOutputsInfo(); - InferenceEngine::BlobMap outputBlobs; - - std::pair item = *out.begin(); - - InferenceEngine::TBlob::Ptr output; - output = InferenceEngine::make_shared_blob(item.second->getTensorDesc()); - output->allocate(); - outputBlobs[item.first] = output; - - inferRequest.SetInput(srcs); - inferRequest.SetOutput(outputBlobs); - inferRequest.Infer(); - - InferenceEngine::TBlob dst_ref(item.second->getTensorDesc()); - dst_ref.allocate(); - - ref_resample(*srcPtr, dst_ref, p); - - compare(*output, dst_ref); - } catch (const InferenceEngine::Exception &e) { - FAIL() << e.what(); - } - } -}; - -TEST_P(ResampleTests, TestsResample) {} diff --git a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/ti_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/ti_tests.hpp index 706fdc1240f..6fd48357cb8 100644 --- a/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/ti_tests.hpp +++ b/inference-engine/tests_deprecated/functional/shared_tests/single_layer_tests/ti_tests.hpp @@ -12,11 +12,9 @@ #include "plg_test.hpp" #include "single_layer_common.hpp" -#include "ir_gen_helper.hpp" using namespace ::testing; using namespace InferenceEngine; -using namespace single_layer_tests; struct ti_test_params { std::string device_name; diff --git a/inference-engine/tests_deprecated/functional/vpu/CMakeLists.txt b/inference-engine/tests_deprecated/functional/vpu/CMakeLists.txt index b3245238c30..5374ecd4519 100644 --- a/inference-engine/tests_deprecated/functional/vpu/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/vpu/CMakeLists.txt @@ -37,6 +37,9 @@ addIeTarget( ${CMAKE_CURRENT_SOURCE_DIR}/common/regression/helpers LINK_LIBRARIES IESharedTests + ieTestHelpers + funcTestUtils + format_reader vpu_graph_transformer vpu_custom_kernels ) @@ -44,6 +47,7 @@ addIeTarget( target_include_directories(VPUCommonTests INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/vpu_base ${CMAKE_CURRENT_SOURCE_DIR}/common/regression/helpers + $ $ ) diff --git a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/reference_regression.cpp b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/reference_regression.cpp index 5330b3627b7..b99a3bbca16 100644 --- a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/reference_regression.cpp +++ b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/reference_regression.cpp @@ -1,15 +1,15 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// +// // Copyright (C) 2018-2021 Intel Corporation +// // SPDX-License-Identifier: Apache-2.0 +// // -#include "regression_reference.hpp" -#include "vpu_tests_config.hpp" +// #include "regression_reference.hpp" +// #include "vpu_tests_config.hpp" -namespace Regression { - namespace Reference { +// namespace Regression { +// namespace Reference { - std::map> values = { - }; +// std::map> values = { +// }; - } // namespace Reference -} // namespace Regression +// } // namespace Reference +// } // namespace Regression diff --git a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_case_common.hpp b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_case_common.hpp index 8047b9d848e..82217999d18 100644 --- a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_case_common.hpp +++ b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_case_common.hpp @@ -7,16 +7,16 @@ #include #include #include -#include +#include #include #include +#include #include #include "vpu_case_params.hpp" #include "vpu_param_containers.hpp" using namespace ::testing; using namespace InferenceEngine; -using namespace Regression::Matchers; #define DISABLE_IF(expr) \ do { \ @@ -62,7 +62,7 @@ using PluginDevicePair = std::pair; // class VpuNoRegressionBase //------------------------------------------------------------------------------ -class VpuNoRegressionBase : public Regression::RegressionTests { +class VpuNoRegressionBase : public TestsCommon { public: //Operations static std::string getTestCaseName(PluginDevicePair, @@ -71,7 +71,7 @@ public: DoReshape); // Accessors - std::string getDeviceName() const override; + std::string getDeviceName() const; protected: // Data section diff --git a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_case_params.hpp b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_case_params.hpp index 55ad08f4a32..4bdd0b55eab 100644 --- a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_case_params.hpp +++ b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_case_params.hpp @@ -4,12 +4,12 @@ #pragma once -#include #include #include +#include +#include +#include -using namespace InferenceEngine; -using namespace Regression::Matchers; using String2StringMap = std::map; using AdditionCfgParamsFactory = std::function; @@ -53,23 +53,12 @@ public: inline ClassificationSrcParam( std::string model_name, std::string img_name, - double reference_delta, - Regression::EMean mean = Regression::EMean::eValues); - - // Accessors - inline Regression::EMean mean() const; - - // Operations - inline std::string name() const override; + double reference_delta); friend std::ostream& operator<<(std::ostream& os, const ClassificationSrcParam& param) { return os << param.modelName() << ", " << param.imageName() << - ", " << std::to_string(param.referenceDelta()) << ", " << format_mean(param.mean()); + ", " << std::to_string(param.referenceDelta()); } - -private: - //Data section - Regression::EMean mean_; }; //------------------------------------------------------------------------------ @@ -136,19 +125,8 @@ inline std::string SourceParameterBase::name() const { inline ClassificationSrcParam::ClassificationSrcParam( std::string model_name, std::string img_name, - double reference_delta, - Regression::EMean mean): - SourceParameterBase(model_name, img_name, reference_delta), - mean_(mean) { -} - -inline Regression::EMean ClassificationSrcParam::mean() const { - return mean_; -} - -inline std::string ClassificationSrcParam::name() const { - return SourceParameterBase::name() + - "_Mean=" + format_mean(mean_); + double reference_delta): + SourceParameterBase(model_name, img_name, reference_delta) { } //------------------------------------------------------------------------------ diff --git a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_classification_case.cpp b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_classification_case.cpp index dd767687613..d4dcc61de90 100644 --- a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_classification_case.cpp +++ b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_classification_case.cpp @@ -3,6 +3,7 @@ // #include "vpu_classification_case.hpp" +#include "functional_test_utils/plugin_cache.hpp" //------------------------------------------------------------------------------ // Implementation of methods of class VpuNoClassificationRegression diff --git a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_classification_case.hpp b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_classification_case.hpp index 81dd646c459..c62aab176b8 100644 --- a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_classification_case.hpp +++ b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_classification_case.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include "vpu_case_common.hpp" using CompilationTestParam = WithParamInterface>; @@ -63,14 +64,14 @@ protected: // class VpuNoRegressionWithCompilation //------------------------------------------------------------------------------ -class VpuNoRegressionWithCompilation : public Regression::RegressionTests, +class VpuNoRegressionWithCompilation : public TestsCommon, public CompilationTestParam { public: // Operations static std::string getTestCaseName(TestParamInfo param); // Accessors - std::string getDeviceName() const override; + std::string getDeviceName() const; protected: // Data section diff --git a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_raw_results_case.cpp b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_raw_results_case.cpp index 94893b8a59d..b5d55ee08f7 100644 --- a/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_raw_results_case.cpp +++ b/inference-engine/tests_deprecated/functional/vpu/common/regression/helpers/vpu_raw_results_case.cpp @@ -4,6 +4,9 @@ #include "vpu_raw_results_case.hpp" +#include +#include + std::vector operator + (std::vector && l, const std::vector & r) { l.insert(l.end(), r.begin(), r.end()); diff --git a/inference-engine/tests_deprecated/functional/vpu/vpu_base/myriad_layers_tests.hpp b/inference-engine/tests_deprecated/functional/vpu/vpu_base/myriad_layers_tests.hpp index 9ec8f77bd94..fa3e86da345 100644 --- a/inference-engine/tests_deprecated/functional/vpu/vpu_base/myriad_layers_tests.hpp +++ b/inference-engine/tests_deprecated/functional/vpu/vpu_base/myriad_layers_tests.hpp @@ -15,6 +15,7 @@ #include #include #include "myriad_layers_reference_functions.hpp" +#include "common_test_utils/xml_net_builder/xml_net_builder.hpp" #include "vpu_layers_tests.hpp" #include diff --git a/inference-engine/tests_deprecated/helpers/CMakeLists.txt b/inference-engine/tests_deprecated/helpers/CMakeLists.txt index 5b9c2258d3a..6a4b0a05be0 100644 --- a/inference-engine/tests_deprecated/helpers/CMakeLists.txt +++ b/inference-engine/tests_deprecated/helpers/CMakeLists.txt @@ -48,3 +48,8 @@ if (ENABLE_DATA) add_dependencies(${TARGET_NAME} data) add_dependencies(${TARGET_NAME}_s data) endif() + +# developer package + +openvino_developer_export_targets(COMPONENT inference_engine_tests + TARGETS ieTestHelpers ieTestHelpers_s) diff --git a/inference-engine/tests_deprecated/functional/ie_tests/src/ie_core_adapter.cpp b/inference-engine/tests_deprecated/helpers/ie_core_adapter.cpp similarity index 100% rename from inference-engine/tests_deprecated/functional/ie_tests/src/ie_core_adapter.cpp rename to inference-engine/tests_deprecated/helpers/ie_core_adapter.cpp diff --git a/inference-engine/tests_deprecated/functional/ie_tests/include/ie_core_adapter.hpp b/inference-engine/tests_deprecated/helpers/ie_core_adapter.hpp similarity index 100% rename from inference-engine/tests_deprecated/functional/ie_tests/include/ie_core_adapter.hpp rename to inference-engine/tests_deprecated/helpers/ie_core_adapter.hpp diff --git a/inference-engine/tests_deprecated/helpers/ir_gen_helper.cpp b/inference-engine/tests_deprecated/helpers/ir_gen_helper.cpp deleted file mode 100644 index e883b516e56..00000000000 --- a/inference-engine/tests_deprecated/helpers/ir_gen_helper.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -#include "ir_gen_helper.hpp" - -namespace single_layer_tests { - - std::string IRTemplateGenerator::getIRTemplate(const std::string& name, - const std::vector& input_shape, - const std::string& precision, - const std::string& layers, - const std::string& edges, - const unsigned ir_version, - const std::string& metadata) { - const std::vector< std::vector> input_shape_vector = { input_shape }; - return getIRTemplate(name, input_shape_vector, precision, layers, edges, ir_version, metadata); - } - std::string IRTemplateGenerator::getIRTemplate(const std::string& name, - const std::vector>& input_shape, - const std::string& precision, - const std::string& layers, - const std::string& edges, - const unsigned ir_version, - const std::string& metadata) { - std::string model = model_t; - REPLACE_WITH_STR(model, "_NAME_", name); - REPLACE_WITH_NUM(model, "_IRv_", ir_version); - std::string input_layers; - for (int i = 0; i < input_shape.size(); i++) { - std::string model_input = model_input_t; - std::string s_dims; - for (auto& dim : input_shape[0]) { - s_dims += "\n\t "; - s_dims += std::to_string(dim) + ""; - } - REPLACE_WITH_STR(model_input, "_ID_", std::to_string(i)); - std::string input_name = "in" + std::to_string(i + 1); - REPLACE_WITH_STR(model_input, "_input_name_", input_name); - REPLACE_WITH_STR(model_input, "__SRC_DIMS__", s_dims); - input_layers += model_input; - } - REPLACE_WITH_STR(model, "__INPUT_LAYERS_", input_layers); - REPLACE_WITH_STR(model, "_PR_", precision); - REPLACE_WITH_STR(model, "_LAYERS_", layers); - REPLACE_WITH_STR(model, "_EDGES_", edges); - REPLACE_WITH_STR(model, "_META_DATA_", metadata); - - return model; - } - - std::string IRTemplateGenerator::model_input_t = R"V0G0N( - - - __SRC_DIMS__ - - - - - )V0G0N"; - - std::string IRTemplateGenerator::model_t = R"V0G0N( - - - __INPUT_LAYERS_ - _LAYERS_ - - - _EDGES_ - - - - _META_DATA_ - - - - )V0G0N"; -} // namespace single_layer_tests diff --git a/inference-engine/tests_deprecated/helpers/ir_gen_helper.hpp b/inference-engine/tests_deprecated/helpers/ir_gen_helper.hpp deleted file mode 100644 index e81aa5febdd..00000000000 --- a/inference-engine/tests_deprecated/helpers/ir_gen_helper.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef IR_GEN_HELPER_HPP -#define IR_GEN_HELPER_HPP - -#include "single_layer_common.hpp" - -namespace single_layer_tests { - - class IRTemplateGenerator { - IRTemplateGenerator() = default; - public: - static std::string model_t; - static std::string model_input_t; - - static std::string getIRTemplate(const std::string& name, - const std::vector& input_shape, - const std::string& precision, - const std::string& layers, - const std::string& edges, - const unsigned ir_version = 5u, - const std::string& metadata = ""); - - - - static std::string getIRTemplate(const std::string& name, - const std::vector>& input_shape, - const std::string& precision, - const std::string& layers, - const std::string& edges, - const unsigned ir_version = 5u, - const std::string& metadata = ""); - - }; - -} // namespace single_layer_tests -#endif /* IR_GEN_HELPER_HPP */ - diff --git a/inference-engine/tests_deprecated/helpers/tests_common_func.cpp b/inference-engine/tests_deprecated/helpers/tests_common_func.cpp deleted file mode 100644 index 5738cf75521..00000000000 --- a/inference-engine/tests_deprecated/helpers/tests_common_func.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include - -#include "tests_common_func.hpp" - -using namespace InferenceEngine; - -inline void bswap_32(char* ptr, size_t size) { - char* end = ptr + size; - char tmp; - for (; ptr < end; ptr+=4) { - tmp = ptr[0]; ptr[0] = ptr[3]; ptr[3] = tmp; - tmp = ptr[1]; ptr[1] = ptr[2]; ptr[2] = tmp; - } -} - -InferenceEngine::Blob::Ptr readBMP(std::string path, unsigned batch) { - - std::ifstream input(path, std::ios::binary); - if (!input) return nullptr; - - unsigned char bmpFileHeader[14]; - input.read((char*)bmpFileHeader, sizeof(bmpFileHeader)); - if(bmpFileHeader[0]!='B' || bmpFileHeader[1]!='M') return nullptr; - if(bmpFileHeader[11]!=0 || bmpFileHeader[12]!=0 || bmpFileHeader[13]!=0 ) return nullptr; - - unsigned char bmpInfoHeader[40]; - input.read((char*)bmpInfoHeader, sizeof(bmpInfoHeader)); - if(bmpInfoHeader[14]!=24) return nullptr; // bits per pixel - if(bmpInfoHeader[16]!=0) return nullptr; // compression is not supported - - bool rowsReversed = (*(int32_t*)(bmpInfoHeader + 8)) < 0; - uint32_t width = *(int32_t*)(bmpInfoHeader + 4); - uint32_t height = abs(*(int32_t*)(bmpInfoHeader + 8)); - - size_t padSize = width & 3; - char pad[3]; - - InferenceEngine::Blob::Ptr blob(new InferenceEngine::TBlob( - {InferenceEngine::Precision::FP32, {batch, 3, height, width}, InferenceEngine::Layout::NCHW})); - blob->allocate(); - float *blob_ptr = (float*)(void*)blob->buffer(); - - unsigned int offset = *(unsigned int *)(bmpFileHeader + 10); - for (int b = 0; b < batch; b++) { - int b_off = 3*width*height*b; - input.seekg(offset, std::ios::beg); - //reading by rows in invert vertically - for (uint32_t i = 0; i < height; i++) { - int storeAt = rowsReversed ? i : height - 1 - i; - - for (uint32_t j = 0; j < width; j++) { - unsigned char RGBA[3]; - input.read((char *) RGBA, sizeof(RGBA)); - - blob_ptr[b_off + j + storeAt * width] = RGBA[0]; - blob_ptr[b_off + j + storeAt * width + height * width * 1] = RGBA[1]; - blob_ptr[b_off + j + storeAt * width + height * width * 2] = RGBA[2]; - } - input.read(pad, padSize); - } - } - - return blob; -} - -InferenceEngine::Blob::Ptr readUbyte(std::string path, unsigned batch) { - - std::ifstream input(path, std::ios::binary); - struct { - uint32_t magic_number; - uint32_t n_images; - uint32_t n_rows; - uint32_t n_cols; - } hdr; - - input.read((char *) &hdr, sizeof(hdr)); - bswap_32((char *) &hdr, sizeof(hdr)); - if (hdr.magic_number != 2051) return nullptr; // Invalid MNIST image file - - InferenceEngine::Blob::Ptr blob(new InferenceEngine::TBlob({InferenceEngine::Precision::FP32, - {batch, hdr.n_images, hdr.n_rows, hdr.n_cols}, - InferenceEngine::NCHW})); - blob->allocate(); - float *blob_ptr = (float*)(void*)blob->buffer(); - for (int b = 0; b < batch; b++) { - input.seekg(sizeof(hdr), std::ios::beg); - int b_off = b*hdr.n_images*hdr.n_rows*hdr.n_cols; - for (uint32_t i = 0; i < hdr.n_images; ++i) { - for (uint32_t r = 0; r < hdr.n_rows; ++r) { - for (uint32_t c = 0; c < hdr.n_cols; ++c) { - unsigned char temp = 0; - input.read((char *) &temp, sizeof(temp)); - blob_ptr[b_off + i * hdr.n_rows * hdr.n_cols + r * hdr.n_cols + c] = temp; - } - } - } - } - return blob; -} - -InferenceEngine::Blob::Ptr TestsCommonFunc::readInput(std::string path, int batch) { - if ( path.substr(path.rfind('.') + 1) == "bmp" ) return readBMP(path, batch); - if ( path.substr(path.rfind('-') + 1) == "ubyte" ) return readUbyte(path, batch); - return nullptr; -} - -bool compareTopLikeObjDetection ( - InferenceEngine::Blob& blob, - std::vector> &ref_top, - int batch_to_compare = 0, - const bool compareRawValues = true) { - assert(blob.getTensorDesc().getDims().back() == 7); - - const int box_info_size = 7; - - int top_num = (int)ref_top.size(); - float *data_ptr = blob.buffer().as(); - const int data_size = blob.size(); - if (data_size/box_info_size < top_num) { - EXPECT_TRUE(data_size/box_info_size >= top_num) << "Dst blob contains less data then expected"; - return false; - } - -#ifdef DISPLAY_RESULTS - std::cout << "actual:" << std::endl; - for (int i = 0; i < top_num; i++) { - std::cout << "{" << data_ptr[i*box_info_size + 1] << ", " << data_ptr[i*box_info_size + 2] << "}" << std::endl; - } - - std::cout << "reference:" << std::endl; - for (int i = 0; i < top_num; i++) { - std::cout << "{" << ref_top[i].first << ", " << ref_top[i].second << "}" << std::endl; - } -#endif - - for (int i=0; i 0.005) { - EXPECT_NEAR(confidence, ref_top[i].second, ref_top[i].second * 0.005); - return false; - } - } - } - - return true; -} - -bool compareTopLikeClassification( - InferenceEngine::Blob& blob, - std::vector> &ref_top, - int batch_to_compare = 0, - float threshold = 0.005f, - const size_t classesCanBeChangedIndex = 9999, - const bool compareRawValues = true) { - int top_num = (int)ref_top.size(); - - size_t data_size = blob.size(); - float *data_ptr = (float*)(void*)blob.buffer(); - - int batch_size = blob.getTensorDesc().getDims()[0]; - assert(batch_size > batch_to_compare); - - const std::vector dims = blob.getTensorDesc().getDims(); - if ((dims.size() != 2ul) || (dims[1] != 1ul)) { - data_size /= batch_size; - } - data_ptr += data_size*batch_to_compare; - - std::vector top(data_size); - - for (size_t i = 0; i < data_size; i++) top[i] = (int)i; - std::partial_sort (top.begin(), top.begin()+top_num, top.end(), - [&](int l, int r) -> bool { return data_ptr[l] > data_ptr[r]; } ); - -#ifdef DISPLAY_RESULTS - std::cout << "actual:" << std::endl; - for (int i = 0; i < top_num; i++) { - std::cout << "{" << top[i] << ", " << data_ptr[top[i]] << "}" << std::endl; - } - - std::cout << "reference:" << std::endl; - for (int i = 0; i < top_num; i++) { - std::cout << "{" << ref_top[i].first << ", " << ref_top[i].second << "}" << std::endl; - } -#endif - - for (int i = 0 ; i < top_num; i++) { - if (top[i] != ref_top[i].first) { - if (i >= classesCanBeChangedIndex) { - bool wasFound = false; - for (int refIndex = 0; refIndex < top_num; refIndex++) { - if (top[i] == ref_top[refIndex].first) { - wasFound = true; - break; - } - } - - if (!wasFound) { - EXPECT_EQ(top[i], ref_top[i].first) << "class is different for element " << i << ": " << top[i] << ", reference: " << ref_top[i].first; - return false; - } - } else { - EXPECT_EQ(top[i], ref_top[i].first) << "class is different for element " << i << ": " << top[i] << ", reference: " << ref_top[i].first; - return false; - } - } - - if (compareRawValues && (fabs(data_ptr[top[i]] - ref_top[i].second)/ref_top[i].second > threshold)) { - EXPECT_NEAR(data_ptr[top[i]] , ref_top[i].second , ref_top[i].second * threshold); - return false; - } - } - return true; -} - -bool TestsCommonFunc::compareTop( - InferenceEngine::Blob& blob, - std::vector> &ref_top, - int batch_to_compare, - float threshold, - const size_t classesCanBeChangedIndex, - const bool compareRawValues) { - if ((blob.getTensorDesc().getDims().size() == 2) && (blob.size() == 3)) { - if (ref_top.size() != blob.size()) { - return false; - } - - const float* buffer = blob.buffer().as(); - -#ifdef DISPLAY_RESULTS - std::cout << "actual:" << std::endl; - for (int i = 0; i < ref_top.size(); i++) { - std::cout << "{" << buffer[i] << "}" << std::endl; - } - - std::cout << "reference:" << std::endl; - for (int i = 0; i < ref_top.size(); i++) { - std::cout << "{" << ref_top[i].first << ", " << ref_top[i].second << "}" << std::endl; - } -#endif - - for (size_t i = 0; i < blob.size(); ++i) { - if (std::abs(ref_top[i].second - buffer[i]) > threshold) { - return false; - } - } - return true; - } else if (blob.getTensorDesc().getDims().back() == 7) - return compareTopLikeObjDetection(blob, ref_top, batch_to_compare, compareRawValues); - else - return compareTopLikeClassification(blob, ref_top, batch_to_compare, threshold, classesCanBeChangedIndex, compareRawValues); -} diff --git a/inference-engine/tests_deprecated/helpers/tests_common_func.hpp b/inference-engine/tests_deprecated/helpers/tests_common_func.hpp deleted file mode 100644 index a66eaae9c7b..00000000000 --- a/inference-engine/tests_deprecated/helpers/tests_common_func.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include - -// use to display additional test info: -// 1. low precision transformation parameters -// 2. reference and actual outputs -// #define DISPLAY_RESULTS - -using namespace InferenceEngine; - -IE_SUPPRESS_DEPRECATED_START - -class TestsCommonFunc { - static CNNLayerPtr getLayer(const CNNNetwork& network, const std::string& layerName) { - std::vector layers = InferenceEngine::details::CNNNetSortTopologically(network); - for (CNNLayerPtr layer : layers) { - if (layer->name == layerName) { - return layer; - } - } - - return nullptr; - } -public: - - InferenceEngine::Blob::Ptr readInput(std::string path, int batch = 1); - - static void checkLayerOuputPrecision( - const CNNNetwork& network, - const std::vector& layerNames, - const Precision expectedPrecision, - const std::string& type = "") { - for (const std::string& layerName : layerNames) { - if (!type.empty()) { - const CNNLayerPtr layer = getLayer(network, layerName); - if (layer == nullptr) { - IE_THROW() << "layer was not found " << layerName; - } - - if (layer->type != type) { - IE_THROW() << "layer '" << layer->name << "' type '" << layer->type << "' is not correct, expected " << type; - } - } - checkLayerOuputPrecision(network, layerName, expectedPrecision); - } - } - - static void checkLayerOuputPrecision(const CNNNetwork& network, const std::string& layerName, Precision expectedPrecision) { - CNNLayerPtr layer = getLayer(network, layerName); - if (layer == nullptr) { - IE_THROW() << "layer '" << layerName << "' was not found"; - } - for (DataPtr data : layer->outData) { - ASSERT_EQ(expectedPrecision, data->getPrecision()) << " unexpected precision " << data->getPrecision() << " for layer " << layerName; - } - } - - static void checkLayerOuputPrecision(const CNNNetwork& network, const std::string& layerName, std::vector expectedPrecisions) { - CNNLayerPtr layer = getLayer(network, layerName); - if (layer == nullptr) { - IE_THROW() << "layer '" << layerName << "' was not found"; - } - for (DataPtr data : layer->outData) { - ASSERT_TRUE(std::any_of( - expectedPrecisions.begin(), - expectedPrecisions.end(), - [&](const Precision precision) { return precision == data->getTensorDesc().getPrecision(); })) << - " unexpected precision " << data->getPrecision() << " for layer " << layerName; - } - } - - bool compareTop( - InferenceEngine::Blob& blob, - std::vector> &ref_top, - int batch_to_compare = 0, - float threshold = 0.005f, - const size_t classesCanBeChangedIndex = 9999, - const bool compareRawValues = true); -}; - -IE_SUPPRESS_DEPRECATED_END diff --git a/inference-engine/tests_deprecated/unit/engines/mkldnn/dummy.cpp b/inference-engine/tests_deprecated/unit/engines/mkldnn/dummy.cpp deleted file mode 100644 index ffe853f7697..00000000000 --- a/inference-engine/tests_deprecated/unit/engines/mkldnn/dummy.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - From a13bd518fc43c0837ad51592bf11bc4890929068 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 12 May 2021 13:24:18 +0300 Subject: [PATCH 27/99] [IE CLDNN] Fixed CLDNN internal tests compilation (#5597) --- inference-engine/src/cldnn_engine/CMakeLists.txt | 2 -- inference-engine/thirdparty/clDNN/CMakeLists.txt | 4 ++-- inference-engine/thirdparty/clDNN/src/CMakeLists.txt | 4 ++++ .../thirdparty/clDNN/src/include/cldnn_itt.h | 2 +- .../clDNN/tests_core_internal/CMakeLists.txt | 12 ++++++++---- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/inference-engine/src/cldnn_engine/CMakeLists.txt b/inference-engine/src/cldnn_engine/CMakeLists.txt index 1ba2bc9e98e..c7ac932910b 100644 --- a/inference-engine/src/cldnn_engine/CMakeLists.txt +++ b/inference-engine/src/cldnn_engine/CMakeLists.txt @@ -40,8 +40,6 @@ target_include_directories(${TARGET_NAME} PRIVATE set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) - -set_ie_threading_interface_for(clDNN_lib) # Failed because of OpenCL # ie_add_api_validator_post_build_step(TARGET ${TARGET_NAME}) diff --git a/inference-engine/thirdparty/clDNN/CMakeLists.txt b/inference-engine/thirdparty/clDNN/CMakeLists.txt index c9cc74e38f7..6c63f932ed1 100644 --- a/inference-engine/thirdparty/clDNN/CMakeLists.txt +++ b/inference-engine/thirdparty/clDNN/CMakeLists.txt @@ -60,9 +60,9 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) # ====================================== HELPER CONSTANT VARIABLES ===================================== # ====================================================================================================== # ====================================================================================================== -if("${CLDNN_THREADING}" MATCHES "SEQ") +if(CLDNN_THREADING MATCHES "SEQ") add_definitions(-DCLDNN_THREADING=CLDNN_THREADING_SEQ) -elseif("${CLDNN_THREADING}" MATCHES "TBB") +elseif(CLDNN_THREADING MATCHES "TBB") add_definitions(-DCLDNN_THREADING=CLDNN_THREADING_TBB) else() add_definitions(-DCLDNN_THREADING=CLDNN_THREADING_THREADPOOL) diff --git a/inference-engine/thirdparty/clDNN/src/CMakeLists.txt b/inference-engine/thirdparty/clDNN/src/CMakeLists.txt index 160492150a4..dd1fd4b300f 100644 --- a/inference-engine/thirdparty/clDNN/src/CMakeLists.txt +++ b/inference-engine/thirdparty/clDNN/src/CMakeLists.txt @@ -157,6 +157,10 @@ target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE openvino::itt ) +if(COMMAND set_ie_threading_interface_for) + set_ie_threading_interface_for("${CLDNN_BUILD__PROJ}") +endif() + if(WIN32) target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE setupapi) elseif((NOT ANDROID) AND (UNIX)) diff --git a/inference-engine/thirdparty/clDNN/src/include/cldnn_itt.h b/inference-engine/thirdparty/clDNN/src/include/cldnn_itt.h index 979ba14aad0..b28db96f295 100644 --- a/inference-engine/thirdparty/clDNN/src/include/cldnn_itt.h +++ b/inference-engine/thirdparty/clDNN/src/include/cldnn_itt.h @@ -14,7 +14,7 @@ namespace cldnn { namespace itt { namespace domains { - OV_ITT_DOMAIN(CLDNN); + OV_ITT_DOMAIN(CLDNN) } } } diff --git a/inference-engine/thirdparty/clDNN/tests_core_internal/CMakeLists.txt b/inference-engine/thirdparty/clDNN/tests_core_internal/CMakeLists.txt index 2d270f7c79d..663f50000cc 100644 --- a/inference-engine/thirdparty/clDNN/tests_core_internal/CMakeLists.txt +++ b/inference-engine/thirdparty/clDNN/tests_core_internal/CMakeLists.txt @@ -107,18 +107,22 @@ add_executable("${CLDNN_BUILD__PROJ}" ${__CLDNN_AllSources} ) +if(COMMAND set_ie_threading_interface_for) + set_ie_threading_interface_for("${CLDNN_BUILD__PROJ}") +endif() + set_property(TARGET "${CLDNN_BUILD__PROJ}" PROPERTY PROJECT_LABEL "${CLDNN_BUILD__PROJ_LABEL}") set_property(TARGET "${CLDNN_BUILD__PROJ}" PROPERTY OUTPUT_NAME "${CLDNN_BUILD__PROJ_OUTPUT_NAME}") # Set library dependencies -target_link_libraries("${CLDNN_BUILD__PROJ}" "${CLDNN_BUILD__PROJ__clDNN}") +target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE "${CLDNN_BUILD__PROJ__clDNN}") if(WIN32) - target_link_libraries("${CLDNN_BUILD__PROJ}" setupapi) + target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE setupapi) elseif((NOT ANDROID) AND (UNIX)) - target_link_libraries("${CLDNN_BUILD__PROJ}" pthread) + target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE pthread) endif() -target_link_libraries("${CLDNN_BUILD__PROJ}" ${CLDNN__SYSTEM_LINK_LIBRARIES}) +target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE ${CLDNN__SYSTEM_LINK_LIBRARIES}) # =================================== Custom pre- and post-steps ======================================= From 6971303856bea7bc8a97f56701b3748f3afd277b Mon Sep 17 00:00:00 2001 From: Gabriele Galiero Casay Date: Wed, 12 May 2021 12:47:50 +0200 Subject: [PATCH 28/99] Revise BatchNormInference Reference Implementation (#5468) * Refactor backend tests * Rewrite reference implementation * Align ref impl signature with order of inputs in v5 * Remove legacy code for training and backprop * BarchNorminference operation class review * Use reference to const in helpers to validate input shapes * Refactor type_prop tests to cover v0 and v5 * Add type_prop tests * epsilon attribute test with invalid value * invalid integer input types * Add serialization single layer test * Add attribute visitor test * Fix arm plugin test failure with dynamic element type * Remove CoordinateTransform index call * Add attribute count to visitor test --- .../serialization/single_layer/batch_norm.cpp | 54 + .../ngraph/runtime/reference/batch_norm.hpp | 187 +--- ngraph/core/src/op/batch_norm.cpp | 12 + ngraph/core/src/validation_util.cpp | 26 +- ngraph/test/CMakeLists.txt | 1 + ngraph/test/backend/batch_norm.in.cpp | 552 +++------- ngraph/test/runtime/ie/unit_test.manifest | 9 - .../runtime/interpreter/evaluates_map.cpp | 4 +- ngraph/test/type_prop/batch_norm.cpp | 979 ++++++++---------- ngraph/test/visitors/op/batch_norm.cpp | 56 + 10 files changed, 740 insertions(+), 1140 deletions(-) create mode 100644 inference-engine/tests/functional/inference_engine/serialization/single_layer/batch_norm.cpp create mode 100644 ngraph/test/visitors/op/batch_norm.cpp diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/batch_norm.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/batch_norm.cpp new file mode 100644 index 00000000000..04d878727b3 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/batch_norm.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "shared_test_classes/single_layer/batch_norm.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + +TEST_P(BatchNormLayerTest, Serialize) { + Serialize(); +} + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; + +const std::vector epsilon = { + 1e-6, + 1e-5, + 1e-4 +}; + +const std::vector> inputShapes = { + {1, 3}, + {2, 5}, + {1, 3, 10}, + {1, 3, 1, 1}, + {2, 5, 4, 4}, +}; + +const auto batchNormParams = testing::Combine( + testing::ValuesIn(epsilon), + 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_BatchNorm_Serialization, + BatchNormLayerTest, + batchNormParams, + BatchNormLayerTest::getTestCaseName +); + +} // namespace diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/batch_norm.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/batch_norm.hpp index e2eeb1ba1cc..48d93baaf23 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/batch_norm.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/batch_norm.hpp @@ -7,15 +7,8 @@ #include #include -#include "ngraph/axis_vector.hpp" #include "ngraph/coordinate_transform.hpp" -#include "ngraph/runtime/reference/add.hpp" -#include "ngraph/runtime/reference/broadcast.hpp" -#include "ngraph/runtime/reference/divide.hpp" -#include "ngraph/runtime/reference/multiply.hpp" -#include "ngraph/runtime/reference/sum.hpp" #include "ngraph/shape.hpp" -#include "ngraph/util.hpp" namespace ngraph { @@ -23,177 +16,37 @@ namespace ngraph { namespace reference { + template + static inline T norm(T val, T mean, T var, T eps) + { + return ((val - mean) / static_cast(std::sqrt(var + eps))); + } + template void batch_norm_inference(float eps, + const T* in, const T* gamma, const T* beta, - const T* input, const T* mean, const T* variance, - T* normed_input, - const Shape& input_shape) + T* out, + const Shape& in_shape) { auto eps_casted = static_cast(eps); - CoordinateTransform input_transform(input_shape); - for (Coordinate input_coord : input_transform) + size_t in_idx = 0; + CoordinateTransform in_transform(in_shape); + for (Coordinate in_coord : in_transform) { - auto channel_num = input_coord[1]; - auto channel_gamma = gamma[channel_num]; - auto channel_beta = beta[channel_num]; - auto channel_mean = mean[channel_num]; - auto channel_var = variance[channel_num]; + auto ch_num = in_coord[1]; + auto ch_gamma = gamma[ch_num]; + auto ch_beta = beta[ch_num]; + auto ch_mean = mean[ch_num]; + auto ch_var = variance[ch_num]; - auto input_index = input_transform.index(input_coord); - auto normalized = - (input[input_index] - channel_mean) / (std::sqrt(channel_var + eps_casted)); - normed_input[input_index] = normalized * channel_gamma + channel_beta; - } - } - - template - void batch_norm_training(float eps, - const T* gamma, - const T* beta, - const T* input, - T* normed_input, - T* mean, - T* variance, - const Shape& input_shape) - { - auto eps_casted = static_cast(eps); - auto channels = input_shape[1]; - - // We use these objects to iterate over the indices in a channel. - // The start and end points for the channel axis are modified in the loop. - Coordinate start_corner; - Coordinate end_corner; - for (size_t i = 0; i < input_shape.size(); i++) - { - start_corner.push_back(0); - end_corner.push_back(input_shape[i]); - } - - for (size_t c = 0; c < channels; c++) - { - T channel_sum = 0; - - start_corner[1] = c; - end_corner[1] = c + 1; - - // Compute the mean - CoordinateTransform input_transform(input_shape, start_corner, end_corner); - for (Coordinate input_coord : input_transform) - { - channel_sum += input[input_transform.index(input_coord)]; - } - T channel_mean = channel_sum / (shape_size(input_shape) / channels); - mean[c] = channel_mean; - - T channel_diff_square_sum = 0; - for (Coordinate input_coord : input_transform) - { - auto centered = input[input_transform.index(input_coord)] - channel_mean; - channel_diff_square_sum += centered * centered; - } - T channel_var = channel_diff_square_sum / (shape_size(input_shape) / channels); - variance[c] = channel_var; - - auto channel_gamma = gamma[c]; - auto channel_beta = beta[c]; - T scale = channel_gamma / std::sqrt(channel_var + eps_casted); - - // Compute the normalized output - for (Coordinate input_coord : input_transform) - { - auto input_index = input_transform.index(input_coord); - normed_input[input_index] = - (input[input_index] - channel_mean) * scale + channel_beta; - } - } - } - - template - void batch_norm_backprop(float eps, - const T* gamma, - const T* /* beta */, - const T* input, - const T* mean, - const T* variance, - const T* delta_normed, - T* delta_input, - T* delta_gamma, - T* delta_beta, - const Shape& input_shape) - { - size_t channel_axis = 1; - auto num_channels = input_shape[channel_axis]; - Shape moment_shape = Shape{num_channels}; - auto input_num_elements = shape_size(input_shape); - auto elements_per_channel = input_num_elements / num_channels; - - Coordinate start_corner; - Coordinate end_corner; - for (size_t i = 0; i < input_shape.size(); i++) - { - start_corner.push_back(0); - end_corner.push_back(input_shape[i]); - } - // The forward computation in gory detail - // input[., C, ...] - // gamma[C] - // beta[C] - // mu[c:C] = sum(input[., c, ...])/elements_per_channel - // var[c:C] = sum(input[., c, ...]^2 - mu[c])/elements_per_channel - // inv_sqrt[c:C] = 1/sqrt(var[c]+epsilon) - // gammad[c:C] = gamma[c]*inv_sqrt[c] - // normed[., c:C, ...] = (input[., c, ...]-mu)*gammad[c]+beta[c] - - for (uint64_t c = 0; c < num_channels; ++c) - { - start_corner[channel_axis] = c; - end_corner[channel_axis] = c + 1; - - CoordinateTransform input_transform(input_shape, start_corner, end_corner); - T delta_beta_sum = 0; - T var = variance[c]; - T mu = mean[c]; - T var_eps = var + static_cast(eps); - T sqrt_var_eps = std::sqrt(var_eps); - T inv_sqrt_var_eps = 1 / sqrt_var_eps; - T gammad = gamma[c] * inv_sqrt_var_eps; - T delta_gammad = 0; - T delta_mu = 0; - for (Coordinate input_coord : input_transform) - { - auto idx = input_transform.index(input_coord); - auto delta_idx = delta_normed[idx]; - auto input_idx = input[idx]; - delta_beta_sum += delta_idx; - delta_gammad += (input_idx - mu) * delta_idx; - T delta_centered = gammad * delta_idx; - delta_input[idx] = delta_centered; - delta_mu -= delta_centered; - } - delta_beta[c] = delta_beta_sum; - delta_gamma[c] = delta_gammad * inv_sqrt_var_eps; - T delta_inv_sqrt = gamma[c] * delta_gammad; - // y = x^(-1/2) - // dy = -(1/2)x^(-3/2) = -y/(2x) dx - T delta_var = -delta_inv_sqrt * inv_sqrt_var_eps / (2 * var_eps); - T delta_two_var_sum = 2 * delta_var / elements_per_channel; - T delta_mu_over_n = delta_mu / elements_per_channel; - for (Coordinate input_coord : input_transform) - { - // v = 1/N sum(x_i - mu)^2 - // dv = 2/N sum[(x_i - mu)dx_i] - 2/N sum[(x_i - mu) dmu] - // = 2/N sum[(x_i - mu)dx_i] - 2/N (Nmu-Nmu) dmu - // = 2/N sum[(x_i - mu)dx_i] - auto idx = input_transform.index(input_coord); - // These two values mostly cancel out so add them first - auto val = delta_input[idx] + delta_mu_over_n; - delta_input[idx] = val + (input[idx] - mu) * delta_two_var_sum; - } + auto normalized = norm(in[in_idx], ch_mean, ch_var, eps_casted); + out[in_idx] = normalized * ch_gamma + ch_beta; + in_idx++; } } } // namespace reference diff --git a/ngraph/core/src/op/batch_norm.cpp b/ngraph/core/src/op/batch_norm.cpp index 8c38a07050d..1f772cf67da 100644 --- a/ngraph/core/src/op/batch_norm.cpp +++ b/ngraph/core/src/op/batch_norm.cpp @@ -40,6 +40,12 @@ void op::v0::BatchNormInference::validate_and_infer_types() PartialShape result_batch_shape; PartialShape result_channel_shape; // unused here + NODE_VALIDATION_CHECK( + this, + m_epsilon > 0, + "Attribute 'epsilon' must have non-zero positive floating-point value. Got: ", + m_epsilon); + set_output_size(1); std::tie(result_et, result_batch_shape, result_channel_shape) = infer_batch_norm_forward(this, @@ -94,6 +100,12 @@ void op::v5::BatchNormInference::validate_and_infer_types() PartialShape result_batch_shape; PartialShape result_channel_shape; // unused here + NODE_VALIDATION_CHECK( + this, + m_epsilon > 0, + "Attribute 'epsilon' must have non-zero positive floating-point value. Got: ", + m_epsilon); + set_output_size(1); std::tie(result_et, result_batch_shape, result_channel_shape) = infer_batch_norm_forward(this, diff --git a/ngraph/core/src/validation_util.cpp b/ngraph/core/src/validation_util.cpp index 2abb3eaf0ec..d41a4334f50 100644 --- a/ngraph/core/src/validation_util.cpp +++ b/ngraph/core/src/validation_util.cpp @@ -580,7 +580,7 @@ static std::tuple infer_batch_norm_fo // messages. std::stringstream ss; bool first = true; - for (auto& inp : channel_shaped_inputs) + for (const auto& inp : channel_shaped_inputs) { if (!first) { @@ -594,24 +594,30 @@ static std::tuple infer_batch_norm_fo // Infer output element type. element::Type et_result{input_element_type}; - for (auto& inp : channel_shaped_inputs) + for (const auto& inp : channel_shaped_inputs) { NODE_VALIDATION_CHECK(node, element::Type::merge(et_result, et_result, inp.m_element_type), "Input element types do not match."); } + NODE_VALIDATION_CHECK(node, + et_result.is_dynamic() || et_result.is_real(), + "Input element types must be floating-point. Got: ", + et_result); + // Extract channel dimension from input shape. Dimension channel_dim{Dimension::dynamic()}; - NODE_VALIDATION_CHECK(node, - input_shape.is_dynamic() || input_shape.rank().get_length() >= 2, - "Input argument must have rank of at least 2 (input argument shape: ", - input_shape, - ")."); - - if (input_shape.rank().is_static()) + Rank input_rank = input_shape.rank(); + if (input_rank.is_static()) { + NODE_VALIDATION_CHECK(node, + input_rank.get_length() >= 2, + "Input argument must have rank of at least 2 (input argument shape: ", + input_shape, + ")."); + channel_dim = input_shape[1]; } @@ -619,7 +625,7 @@ static std::tuple infer_batch_norm_fo // "channel_dim". PartialShape channel_shape{PartialShape::dynamic()}; - for (auto& inp : channel_shaped_inputs) + for (const auto& inp : channel_shaped_inputs) { NODE_VALIDATION_CHECK(node, PartialShape::merge_into(channel_shape, inp.m_shape), diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index d4aabfccf8a..ea68af8da22 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -210,6 +210,7 @@ set(SRC visitors/partial_shape.cpp visitors/user_op.cpp visitors/value_map.cpp + visitors/op/batch_norm.cpp visitors/op/broadcast.cpp visitors/op/bucketize.cpp visitors/op/constant.cpp diff --git a/ngraph/test/backend/batch_norm.in.cpp b/ngraph/test/backend/batch_norm.in.cpp index 663935352aa..0e6419318d8 100644 --- a/ngraph/test/backend/batch_norm.in.cpp +++ b/ngraph/test/backend/batch_norm.in.cpp @@ -4,450 +4,154 @@ #include "gtest/gtest.h" #include "ngraph/ngraph.hpp" -#include "ngraph/runtime/tensor.hpp" -#include "runtime/backend.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/ndarray.hpp" +#include "util/test_case.hpp" +#include "util/engine/test_engines.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}); -template -class BatchNormInferenceTester +template +struct BatchNormTestParams { -public: - BatchNormInferenceTester(const std::shared_ptr& backend, - const Shape& input_shape, - element::Type etype, - double epsilon) - : m_backend(backend) - { - Shape channel_shape{input_shape.at(1)}; - - auto Input = make_shared(etype, input_shape); - auto Gamma = make_shared(etype, channel_shape); - auto Beta = make_shared(etype, channel_shape); - auto Mean = make_shared(etype, channel_shape); - auto Variance = make_shared(etype, channel_shape); - auto BN = - make_shared(Input, Gamma, Beta, Mean, Variance, epsilon); - m_function = make_shared(BN, ParameterVector{Input, Gamma, Beta, Mean, Variance}); - - m_input = backend->create_tensor(etype, input_shape); - m_gamma = backend->create_tensor(etype, channel_shape); - m_beta = backend->create_tensor(etype, channel_shape); - m_mean = backend->create_tensor(etype, channel_shape); - m_variance = backend->create_tensor(etype, channel_shape); - m_normed_input = backend->create_tensor(etype, input_shape); - } - - bool call(const std::vector& input, - const std::vector& gamma, - const std::vector& beta, - const std::vector& mean, - const std::vector& variance, - const std::vector& normed_input) - { - copy_data(m_input, input); - copy_data(m_gamma, gamma); - copy_data(m_beta, beta); - copy_data(m_mean, mean); - copy_data(m_variance, variance); - auto handle = m_backend->compile(m_function); - handle->call_with_validate({m_normed_input}, - {m_input, m_gamma, m_beta, m_mean, m_variance}); - auto res_normed_input = read_vector(m_normed_input); - return test::all_close(normed_input, res_normed_input); - } - -protected: - const std::shared_ptr& m_backend; - std::shared_ptr m_function; - std::shared_ptr m_input; - std::shared_ptr m_gamma; - std::shared_ptr m_beta; - std::shared_ptr m_mean; - std::shared_ptr m_variance; - std::shared_ptr m_normed_input; + std::vector in; + Shape in_shape; + std::vector in_g; + std::vector in_b; + std::vector in_m; + std::vector in_v; + float epsilon; + std::vector out; }; template -class BatchNormInferenceTesterZeroEpsilon : public BatchNormInferenceTester +static void BatchNormInferenceTest(const BatchNormTestParams& p) { -public: - // These are for documentation purposes only below - using Input = test::NDArray; - using Gamma = test::NDArray; - using Beta = test::NDArray; - using Mean = test::NDArray; - using Variance = test::NDArray; - using NormedInput = test::NDArray; - - BatchNormInferenceTesterZeroEpsilon(const std::shared_ptr& backend, - element::Type etype) - : BatchNormInferenceTester(backend, Shape{2, 3}, etype, 0.0) - { - } - - bool test(const Input& input, - const Gamma& gamma, - const Beta& beta, - const Mean& mean, - const Variance& variance, - const NormedInput& normed_input) - { - return BatchNormInferenceTester::call(input.get_vector(), - gamma.get_vector(), - beta.get_vector(), - mean.get_vector(), - variance.get_vector(), - normed_input.get_vector()); - } - bool test_gamma() - { - return test(Input{{1.0, 2.0, 3.0}, {-1.0, -2.0, -3.0}}, - Gamma{2.0, 3.0, 4.0}, - Beta{0.0, 0.0, 0.0}, - Mean{0.0, 0.0, 0.0}, - Variance{1.0, 1.0, 1.0}, - NormedInput{{2.0, 6.0, 12.0}, {-2.0, -6.0, -12.0}}); - } - bool test_beta() - { - return test(Input{{1.0, 2.0, 3.0}, {-1.0, -2.0, -3.0}}, - Gamma{1.0, 1.0, 1.0}, - Beta{2.0, -2.0, 3.0}, - Mean{0.0, 0.0, 0.0}, - Variance{1.0, 1.0, 1.0}, - NormedInput{{3.0, 0.0, 6.0}, {1.0, -4.0, 0.0}}); - } - bool test_mean() - { - return test(Input{{1.0, 2.0, 3.0}, {-1.0, -2.0, -3.0}}, - Gamma{1.0, 1.0, 1.0}, - Beta{0.0, 0.0, 0.0}, - Mean{-2.0, 2.0, -3.0}, - Variance{1.0, 1.0, 1.0}, - NormedInput{{3.0, 0.0, 6.0}, {1.0, -4.0, 0.0}}); - } - bool test_variance() - { - return test(Input{{1.0, 2.0, 3.0}, {-1.0, -2.0, -3.0}}, - Gamma{1.0, 1.0, 1.0}, - Beta{0.0, 0.0, 0.0}, - Mean{0.0, 0.0, 0.0}, - Variance{0.25, .0625, 4.0}, - NormedInput{{2.0, 8.0, 1.5}, {-2.0, -8.0, -1.5}}); - } -}; - -NGRAPH_TEST(${BACKEND_NAME}, batch_norm_inference_0eps_f64) -{ - using T = double; - auto& et = element::f64; - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - BatchNormInferenceTesterZeroEpsilon bnt(backend, et); - EXPECT_TRUE(bnt.test_gamma()) << "Gamma test"; - EXPECT_TRUE(bnt.test_beta()) << "Beta test"; - EXPECT_TRUE(bnt.test_mean()) << "Mean test"; - EXPECT_TRUE(bnt.test_variance()) << "Variance test"; + const Shape ch_shape{p.in_shape.at(1)}; + auto input = make_shared(element::from(), p.in_shape); + auto gamma = make_shared(element::from(), ch_shape); + auto beta = make_shared(element::from(), ch_shape); + auto mean = make_shared(element::from(), ch_shape); + auto variance = make_shared(element::from(), ch_shape); + auto batch_norm = make_shared( + input, + gamma, + beta, + mean, + variance, + p.epsilon); + auto f = make_shared( + batch_norm, ParameterVector{input, gamma, beta, mean, variance}); + auto test_case = test::TestCase(f); + test_case.add_input(p.in_shape, p.in); + test_case.add_input(ch_shape, p.in_g); + test_case.add_input(ch_shape, p.in_b); + test_case.add_input(ch_shape, p.in_m); + test_case.add_input(ch_shape, p.in_v); + test_case.add_expected_output(p.in_shape, p.out); + test_case.run_with_tolerance_as_fp(1e-4f); } -NGRAPH_TEST(${BACKEND_NAME}, batch_norm_inference_0eps_f32) +NGRAPH_TEST(${BACKEND_NAME}, batch_norm_inference_2d_f32) { - using T = float; - auto& et = element::f32; - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - BatchNormInferenceTesterZeroEpsilon bnt(backend, et); - EXPECT_TRUE(bnt.test_gamma()) << "Gamma test"; - EXPECT_TRUE(bnt.test_beta()) << "Beta test"; - EXPECT_TRUE(bnt.test_mean()) << "Mean test"; - EXPECT_TRUE(bnt.test_variance()) << "Variance test"; -} + const std::vector> batch_norm_tests{ + BatchNormTestParams{ + {1.0, 2.0, 3.0, -1.0, -2.0, -3.0}, + Shape{2, 3}, + {2.0, 3.0, 4.0}, + {0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0}, + {0.75, 0.75, 0.75}, + 0.25, + {2.0, 6.0, 12.0, -2.0, -6.0, -12.0}}, -template -class BatchNormInferenceTesterNonZeroEpsilon : public BatchNormInferenceTester -{ -public: - // These are for documentation purposes only below - using Input = test::NDArray; - using Gamma = test::NDArray; - using Beta = test::NDArray; - using Mean = test::NDArray; - using Variance = test::NDArray; - using NormedInput = test::NDArray; + BatchNormTestParams{ + {1.0, 2.0, 3.0, -1.0, -2.0, -3.0}, + Shape{2, 3}, + {1.0, 1.0, 1.0}, + {2.0, -2.0, 3.0}, + {0.0, 0.0, 0.0}, + {0.75, 0.75, 0.75}, + 0.25, + {3.0, 0.0, 6.0, 1.0, -4.0, 0.0}}, - BatchNormInferenceTesterNonZeroEpsilon(const std::shared_ptr& backend, - element::Type etype) - : BatchNormInferenceTester(backend, Shape{2, 3}, etype, 0.25) + BatchNormTestParams{ + {1.0, 2.0, 3.0, -1.0, -2.0, -3.0}, + Shape{2, 3}, + {1.0, 1.0, 1.0}, + {0.0, 0.0, 0.0}, + {-2.0, 2.0, -3.0}, + {0.75, 0.75, 0.75}, + 0.25, + {3.0, 0.0, 6.0, 1.0, -4.0, 0.0}}, + + BatchNormTestParams{ + {3.0, 5.0, 1.0, -3.0, -5.0, -1.0}, + Shape{2, 3}, + {1.0, 1.0, 1.0}, + {0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0}, + {2.0, 6.0, 0.0}, + 0.25, + {2.0, 2.0, 2.0, -2.0, -2.0, -2.0}}, + }; + + for(const auto& test_case : batch_norm_tests) { + BatchNormInferenceTest(test_case); } +} - bool test(const Input& input, - const Gamma& gamma, - const Beta& beta, - const Mean& mean, - const Variance& variance, - const NormedInput& normed_input) +NGRAPH_TEST(${BACKEND_NAME}, batch_norm_inference_4d_f32) +{ + float eps = 0.001; + Shape in_shape{2, 2, 2, 1}; + + std::vector in{0.54881352f, + 0.71518934f, + 0.60276335f, + 0.54488319f, + 0.42365479f, + 0.64589411f, + 0.4375872f, + 0.89177299f}; + + std::vector> ch_in_1{{1.0, 1.0}, + {1.0, 1.0}, + {1.0, 1.0}, + {1.0, 1.0}}; + std::vector out_1{0.54903894f, + 0.71533161f, + 0.60296183f, + 0.54511058f, + 0.42394274f, + 0.64607101f, + 0.43786817f, + 0.89182704f}; + + std::vector> ch_in_2{{1.0, 1.0}, + {0.0f, 0.0f}, + {0.583388f, 0.619252f}, + {0.0119972f, 0.0282681f}}; + std::vector out_2{-0.30327f, + 1.1561f, + -0.096382f, + -0.434702f, + -1.4011f, + 0.548275f, + -1.06187f, + 1.59295f}; + + const std::vector> batch_norm_tests{ + BatchNormTestParams{in, in_shape, ch_in_1[0], ch_in_1[1], ch_in_1[2], ch_in_1[3], eps, out_1}, + BatchNormTestParams{in, in_shape, ch_in_2[0], ch_in_2[1], ch_in_2[2], ch_in_2[3], eps, out_2} + }; + + for(const auto& test_case : batch_norm_tests) { - return BatchNormInferenceTester::call(input.get_vector(), - gamma.get_vector(), - beta.get_vector(), - mean.get_vector(), - variance.get_vector(), - normed_input.get_vector()); + BatchNormInferenceTest(test_case); } - bool test_gamma() - { - return test(Input{{1.0, 2.0, 3.0}, {-1.0, -2.0, -3.0}}, - Gamma{2.0, 3.0, 4.0}, - Beta{0.0, 0.0, 0.0}, - Mean{0.0, 0.0, 0.0}, - Variance{0.75, 0.75, 0.75}, - NormedInput{{2.0, 6.0, 12.0}, {-2.0, -6.0, -12.0}}); - } - bool test_beta() - { - return test(Input{{1.0, 2.0, 3.0}, {-1.0, -2.0, -3.0}}, - Gamma{1.0, 1.0, 1.0}, - Beta{2.0, -2.0, 3.0}, - Mean{0.0, 0.0, 0.0}, - Variance{0.75, 0.75, 0.75}, - NormedInput{{3.0, 0.0, 6.0}, {1.0, -4.0, 0.0}}); - } - bool test_mean() - { - return test(Input{{1.0, 2.0, 3.0}, {-1.0, -2.0, -3.0}}, - Gamma{1.0, 1.0, 1.0}, - Beta{0.0, 0.0, 0.0}, - Mean{-2.0, 2.0, -3.0}, - Variance{0.75, 0.75, 0.75}, - NormedInput{{3.0, 0.0, 6.0}, {1.0, -4.0, 0.0}}); - } - bool test_variance() - { - return test(Input{{3.0, 5.0, 1.0}, {-3.0, -5.0, -1.0}}, - Gamma{1.0, 1.0, 1.0}, - Beta{0.0, 0.0, 0.0}, - Mean{0.0, 0.0, 0.0}, - Variance{2.0, 6.0, 0.0}, - NormedInput{{2.0, 2.0, 2.0}, {-2.0, -2.0, -2.0}}); - } -}; - -NGRAPH_TEST(${BACKEND_NAME}, batch_norm_inference_f64) -{ - using T = double; - auto& et = element::f64; - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - BatchNormInferenceTesterNonZeroEpsilon bnt(backend, et); - EXPECT_TRUE(bnt.test_gamma()) << "Gamma test"; - EXPECT_TRUE(bnt.test_beta()) << "Beta test"; - EXPECT_TRUE(bnt.test_mean()) << "Mean test"; - EXPECT_TRUE(bnt.test_variance()) << "Variance test"; -} - -NGRAPH_TEST(${BACKEND_NAME}, batch_norm_inference_f32) -{ - using T = float; - auto& et = element::f32; - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - BatchNormInferenceTesterNonZeroEpsilon bnt(backend, et); - EXPECT_TRUE(bnt.test_gamma()) << "Gamma test"; - EXPECT_TRUE(bnt.test_beta()) << "Beta test"; - EXPECT_TRUE(bnt.test_mean()) << "Mean test"; - EXPECT_TRUE(bnt.test_variance()) << "Variance test"; -} - -NGRAPH_TEST(${BACKEND_NAME}, batch_norm_inference_parameters_duplication) -{ - auto input_shape = Shape{2, 2, 2, 1}; - auto input = make_shared(element::f32, input_shape); - - auto mvgb_shape = Shape{2}; - auto mvgb = make_shared(element::f32, mvgb_shape); - - double eps = 0.001; - auto shape_r = Shape{2, 2, 2, 1}; - auto bn = make_shared(input, mvgb, mvgb, mvgb, mvgb, eps); - - auto f = make_shared(bn, ParameterVector{input, mvgb, mvgb, mvgb, mvgb}); - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - // Create some tensors for input/output - auto _input = backend->create_tensor(element::f32, input_shape); - copy_data(_input, - vector{0.54881352f, - 0.71518934f, - 0.60276335f, - 0.54488319f, - 0.42365479f, - 0.64589411f, - 0.4375872f, - 0.89177299f}); - - auto _mvgb = backend->create_tensor(element::f32, mvgb_shape); - copy_data(_mvgb, vector{1.0f, 1.0f}); - auto bn_output = backend->create_tensor(element::f32, shape_r); - - vector expected_result{0.54903894f, - 0.71533161f, - 0.60296183f, - 0.54511058f, - 0.42394274f, - 0.64607101f, - 0.43786817f, - 0.89182704f}; - auto handle = backend->compile(f); - handle->call_with_validate({bn_output}, {_input, _mvgb, _mvgb, _mvgb, _mvgb}); - - ASSERT_TRUE( - ngraph::test::all_close(expected_result, read_vector(bn_output), 1e-3f, 1e-4f)); -} - -NGRAPH_TEST(${BACKEND_NAME}, batch_norm_inference_parameters_duplication_v5) -{ - auto input_shape = Shape{2, 2, 2, 1}; - auto input = make_shared(element::f32, input_shape); - - auto mvgb_shape = Shape{2}; - auto mvgb = make_shared(element::f32, mvgb_shape); - - double eps = 0.001; - auto shape_r = Shape{2, 2, 2, 1}; - auto bn = make_shared(input, mvgb, mvgb, mvgb, mvgb, eps); - - auto f = make_shared(bn, ParameterVector{input, mvgb, mvgb, mvgb, mvgb}); - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - // Create some tensors for input/output - auto _input = backend->create_tensor(element::f32, input_shape); - copy_data(_input, - vector{0.54881352f, - 0.71518934f, - 0.60276335f, - 0.54488319f, - 0.42365479f, - 0.64589411f, - 0.4375872f, - 0.89177299f}); - - auto _mvgb = backend->create_tensor(element::f32, mvgb_shape); - copy_data(_mvgb, vector{1.0f, 1.0f}); - auto bn_output = backend->create_tensor(element::f32, shape_r); - - vector expected_result{0.54903894f, - 0.71533161f, - 0.60296183f, - 0.54511058f, - 0.42394274f, - 0.64607101f, - 0.43786817f, - 0.89182704f}; - auto handle = backend->compile(f); - handle->call_with_validate({bn_output}, {_input, _mvgb, _mvgb, _mvgb, _mvgb}); - - ASSERT_TRUE( - ngraph::test::all_close(expected_result, read_vector(bn_output), 1e-3f, 1e-4f)); -} - -NGRAPH_TEST(${BACKEND_NAME}, batch_norm_fprop_inference_b2c2h2w1) -{ - auto input_shape = Shape{2, 2, 2, 1}; - auto input = make_shared(element::f32, input_shape); - auto gamma_shape = Shape{2}; - auto gamma = make_shared(element::f32, gamma_shape); - auto beta_shape = Shape{2}; - auto beta = make_shared(element::f32, beta_shape); - auto mean_shape = Shape{2}; - auto mean = make_shared(element::f32, mean_shape); - auto var_shape = Shape{2}; - auto var = make_shared(element::f32, var_shape); - double eps = 0.001; - auto shape_r = Shape{2, 2, 2, 1}; - auto bn = make_shared(input, gamma, beta, mean, var, eps); - - auto f = make_shared(bn, ParameterVector{input, gamma, beta, mean, var}); - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - // Create some tensors for input/output - auto _input = backend->create_tensor(element::f32, input_shape); - copy_data(_input, - vector{0.54881352f, - 0.71518934f, - 0.60276335f, - 0.54488319f, - 0.42365479f, - 0.64589411f, - 0.4375872f, - 0.89177299f}); - - auto _gamma = backend->create_tensor(element::f32, gamma_shape); - copy_data(_gamma, vector{1.0f, 1.0f}); - auto _beta = backend->create_tensor(element::f32, beta_shape); - copy_data(_beta, vector{0.0f, 0.0f}); - auto _mean = backend->create_tensor(element::f32, mean_shape); - copy_data(_mean, vector{0.583388f, 0.619252f}); - auto _var = backend->create_tensor(element::f32, var_shape); - copy_data(_var, vector{0.0119972f, 0.0282681f}); - auto bn_output = backend->create_tensor(element::f32, shape_r); - - vector expected_result{ - -0.30327f, 1.1561f, -0.0963782f, -0.434702f, -1.4011f, 0.548275f, -1.06187f, 1.59295f}; - auto handle = backend->compile(f); - handle->call_with_validate({bn_output}, {_input, _gamma, _beta, _mean, _var}); - - ASSERT_TRUE( - ngraph::test::all_close(expected_result, read_vector(bn_output), 1e-3f, 1e-4f)); -} - -NGRAPH_TEST(${BACKEND_NAME}, batch_norm_fprop_inference_b2c2h2w1_v5) -{ - auto input_shape = Shape{2, 2, 2, 1}; - auto input = make_shared(element::f32, input_shape); - auto gamma_shape = Shape{2}; - auto gamma = make_shared(element::f32, gamma_shape); - auto beta_shape = Shape{2}; - auto beta = make_shared(element::f32, beta_shape); - auto mean_shape = Shape{2}; - auto mean = make_shared(element::f32, mean_shape); - auto var_shape = Shape{2}; - auto var = make_shared(element::f32, var_shape); - double eps = 0.001; - auto shape_r = Shape{2, 2, 2, 1}; - auto bn = make_shared(input, gamma, beta, mean, var, eps); - - auto f = make_shared(bn, ParameterVector{input, gamma, beta, mean, var}); - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - // Create some tensors for input/output - auto _input = backend->create_tensor(element::f32, input_shape); - copy_data(_input, - vector{0.54881352f, - 0.71518934f, - 0.60276335f, - 0.54488319f, - 0.42365479f, - 0.64589411f, - 0.4375872f, - 0.89177299f}); - - auto _gamma = backend->create_tensor(element::f32, gamma_shape); - copy_data(_gamma, vector{1.0f, 1.0f}); - auto _beta = backend->create_tensor(element::f32, beta_shape); - copy_data(_beta, vector{0.0f, 0.0f}); - auto _mean = backend->create_tensor(element::f32, mean_shape); - copy_data(_mean, vector{0.583388f, 0.619252f}); - auto _var = backend->create_tensor(element::f32, var_shape); - copy_data(_var, vector{0.0119972f, 0.0282681f}); - auto bn_output = backend->create_tensor(element::f32, shape_r); - - vector expected_result{ - -0.30327f, 1.1561f, -0.0963782f, -0.434702f, -1.4011f, 0.548275f, -1.06187f, 1.59295f}; - auto handle = backend->compile(f); - handle->call_with_validate({bn_output}, {_input, _gamma, _beta, _mean, _var}); - - ASSERT_TRUE( - ngraph::test::all_close(expected_result, read_vector(bn_output), 1e-3f, 1e-4f)); } diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index ceeaa049648..cac9e71d603 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -950,15 +950,6 @@ gelu_f64 gelu_backprop_factor_f32 gelu_backprop_factor_f64 -# Incorrect precision f64! -batch_norm_inference_0eps_f64 -batch_norm_inference_f64 -batch_norm_training_0eps_f64 - -# Function inputs number differ from number of given inputs -batch_norm_inference_parameters_duplication -batch_norm_inference_parameters_duplication_v5 - backwards_abs backwards_acos backwards_add diff --git a/ngraph/test/runtime/interpreter/evaluates_map.cpp b/ngraph/test/runtime/interpreter/evaluates_map.cpp index 8ab43d6e8ef..1fc9a8d2f8f 100644 --- a/ngraph/test/runtime/interpreter/evaluates_map.cpp +++ b/ngraph/test/runtime/interpreter/evaluates_map.cpp @@ -1379,9 +1379,9 @@ namespace { using T = typename element_type_traits::value_type; runtime::reference::batch_norm_inference(op->get_eps_value(), + inputs[2]->get_data_ptr(), inputs[0]->get_data_ptr(), inputs[1]->get_data_ptr(), - inputs[2]->get_data_ptr(), inputs[3]->get_data_ptr(), inputs[4]->get_data_ptr(), outputs[0]->get_data_ptr(), @@ -1396,9 +1396,9 @@ namespace { using T = typename element_type_traits::value_type; runtime::reference::batch_norm_inference(op->get_eps_value(), + inputs[0]->get_data_ptr(), inputs[1]->get_data_ptr(), inputs[2]->get_data_ptr(), - inputs[0]->get_data_ptr(), inputs[3]->get_data_ptr(), inputs[4]->get_data_ptr(), outputs[0]->get_data_ptr(), diff --git a/ngraph/test/type_prop/batch_norm.cpp b/ngraph/test/type_prop/batch_norm.cpp index e9185988975..13abbdf5a4f 100644 --- a/ngraph/test/type_prop/batch_norm.cpp +++ b/ngraph/test/type_prop/batch_norm.cpp @@ -9,614 +9,537 @@ using namespace std; using namespace ngraph; -TEST(type_prop, batch_norm_inference_partial_all_rank_dynamic) +struct BatchNormInferInputs { - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{PartialShape::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{PartialShape::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; + element::Type in_et; + PartialShape in_shape; + std::string in_name; +}; + +struct BatchNormInferParams +{ + element::Type data_batch_et; + PartialShape data_batch_ps; + std::vector inputs; + double epsilon; +}; + +template +std::shared_ptr makeBatchNormOp(const BatchNormInferParams& p) +{ + if(p.inputs.size() != 4) + { + throw runtime_error("BatchNormInference requires 4 additional inputs for batch" + "normalization transformation"); + } + auto data_batch = make_shared(p.data_batch_et, p.data_batch_ps); + auto gamma = make_shared(p.inputs[0].in_et, p.inputs[0].in_shape); + auto beta = make_shared(p.inputs[1].in_et, p.inputs[1].in_shape); + auto mean = make_shared(p.inputs[2].in_et, p.inputs[2].in_shape); + auto variance = make_shared(p.inputs[3].in_et, p.inputs[3].in_shape); + return make_shared(data_batch, gamma, beta, mean, variance, p.epsilon); +} + +template +class BatchNormTest : public ::testing::Test +{ +}; + +TYPED_TEST_CASE_P(BatchNormTest); + +TYPED_TEST_P(BatchNormTest, batch_norm_inference_basic_data_batch_rank_2) +{ + PartialShape data_batch_shape{10, 100}; + element::Type inputs_et = element::f32; + + std::vector ch_inputs = + { + {inputs_et, PartialShape{100}, "gamma"}, + {inputs_et, PartialShape{100}, "beta"}, + {inputs_et, PartialShape{100}, "mean"}, + {inputs_et, PartialShape{100}, "variance"} + }; + double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - auto bn = - make_shared(data_batch, gamma, beta, mean, variance, epsilon); + const BatchNormInferParams params{inputs_et, data_batch_shape, ch_inputs, epsilon}; + auto bn = makeBatchNormOp(params); ASSERT_EQ(bn->get_output_size(), 1); - ASSERT_EQ(bn->get_output_element_type(0), data_batch_et); + ASSERT_EQ(bn->get_output_element_type(0), inputs_et); + ASSERT_TRUE(bn->get_output_partial_shape(0).rank().is_static()); + ASSERT_TRUE(bn->get_output_partial_shape(0).same_scheme(data_batch_shape)); +} + +TYPED_TEST_P(BatchNormTest, batch_norm_inference_basic_data_batch_rank_4) +{ + PartialShape data_batch_shape{1, 10, 224, 224}; + element::Type inputs_et = element::f16; + + std::vector ch_inputs = + { + {inputs_et, PartialShape{10}, "gamma"}, + {inputs_et, PartialShape{10}, "beta"}, + {inputs_et, PartialShape{10}, "mean"}, + {inputs_et, PartialShape{10}, "variance"} + }; + + double epsilon = 0.001; + + const BatchNormInferParams params{inputs_et, data_batch_shape, ch_inputs, epsilon}; + auto bn = makeBatchNormOp(params); + + ASSERT_EQ(bn->get_output_size(), 1); + ASSERT_EQ(bn->get_output_element_type(0), inputs_et); + ASSERT_TRUE(bn->get_output_partial_shape(0).rank().is_static()); + ASSERT_TRUE(bn->get_output_partial_shape(0).same_scheme(data_batch_shape)); +} + +TYPED_TEST_P(BatchNormTest, batch_norm_inference_inputs_rank_dynamic) +{ + PartialShape data_batch_shape{PartialShape::dynamic()}; + element::Type inputs_et = element::f32; + + std::vector ch_inputs = + { + {inputs_et, PartialShape::dynamic(), "gamma"}, + {inputs_et, PartialShape::dynamic(), "beta"}, + {inputs_et, PartialShape::dynamic(), "mean"}, + {inputs_et, PartialShape::dynamic(), "variance"} + }; + + double epsilon = 0.001; + + const BatchNormInferParams params{inputs_et, data_batch_shape, ch_inputs, epsilon}; + auto bn = makeBatchNormOp(params); + + ASSERT_EQ(bn->get_output_size(), 1); + ASSERT_EQ(bn->get_output_element_type(0), inputs_et); ASSERT_TRUE(bn->get_output_partial_shape(0).rank().is_dynamic()); } -TEST(type_prop, batch_norm_inference_partial_input_rank_static_dynamic_ok) +TYPED_TEST_P(BatchNormTest, batch_norm_inference_data_batch_rank_static_channel_inputs_rank_dynamic) { PartialShape data_batch_shape{ 64, Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}; - PartialShape gamma_shape{PartialShape::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{PartialShape::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; + element::Type inputs_et = element::f32; + + std::vector ch_inputs = + { + {inputs_et, PartialShape::dynamic(), "gamma"}, + {inputs_et, PartialShape::dynamic(), "beta"}, + {inputs_et, PartialShape::dynamic(), "mean"}, + {inputs_et, PartialShape::dynamic(), "variance"} + }; + double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - auto bn = - make_shared(data_batch, gamma, beta, mean, variance, epsilon); + const BatchNormInferParams params{inputs_et, data_batch_shape, ch_inputs, epsilon}; + auto bn = makeBatchNormOp(params); ASSERT_EQ(bn->get_output_size(), 1); - ASSERT_EQ(bn->get_output_element_type(0), data_batch_et); + ASSERT_EQ(bn->get_output_element_type(0), inputs_et); ASSERT_TRUE(bn->get_output_partial_shape(0).same_scheme( PartialShape{64, Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()})); } -TEST(type_prop, batch_norm_inference_partial_input_rank_static_dynamic_zero_channels) -{ - PartialShape data_batch_shape{ - Dimension::dynamic(), 0, Dimension::dynamic(), Dimension::dynamic()}; - PartialShape gamma_shape{PartialShape::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{PartialShape::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - try - { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Zero channel count not detected"; - } - catch (const NodeValidationFailure& error) - { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Channel count must be at least 1")); - } - catch (...) - { - FAIL() << "Deduced type check failed for unexpected reason"; - } -} - -TEST(type_prop, batch_norm_inference_partial_input_rank_dynamic_some_rank_static_dynamic_ok) +TYPED_TEST_P( + BatchNormTest, + batch_norm_inference_data_batch_rank_dynamic_some_channel_inputs_rank_static) { PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{Dimension::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{Dimension::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; + element::Type input_et = element::f32; + + std::vector inputs = + { + {input_et, PartialShape{Dimension::dynamic()}, "gamma"}, + {input_et, PartialShape::dynamic(), "beta"}, + {input_et, PartialShape{Dimension::dynamic()}, "mean"}, + {input_et, PartialShape::dynamic(), "variance"} + }; + double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - auto bn = - make_shared(data_batch, gamma, beta, mean, variance, epsilon); + const BatchNormInferParams params{input_et, data_batch_shape, inputs, epsilon}; + auto bn = makeBatchNormOp(params); ASSERT_EQ(bn->get_output_size(), 1); - ASSERT_EQ(bn->get_output_element_type(0), data_batch_et); + ASSERT_EQ(bn->get_output_element_type(0), input_et); ASSERT_TRUE(bn->get_output_partial_shape(0).rank().is_dynamic()); } -TEST(type_prop, batch_norm_inference_partial_input_rank_dynamic_some_rank_static_dynamic_wrong_rank) +TYPED_TEST_P(BatchNormTest, + batch_norm_inference_data_batch_rank_static_some_channel_inputs_rank_static) { - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{Dimension::dynamic(), Dimension::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{Dimension::dynamic(), Dimension::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; + PartialShape data_batch_shape{64, Dimension::dynamic(), Dimension::dynamic(), 224}; + element::Type input_et = element::f32; + + std::vector inputs = + { + {input_et, PartialShape{3}, "gamma"}, + {input_et, PartialShape::dynamic(), "beta"}, + {input_et, PartialShape{3}, "mean"}, + {input_et, PartialShape{Dimension::dynamic()}, "variance"} + }; + double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); + const BatchNormInferParams params{input_et, data_batch_shape, inputs, epsilon}; + auto bn = makeBatchNormOp(params); + ASSERT_EQ(bn->get_output_size(), 1); + ASSERT_EQ(bn->get_output_element_type(0), input_et); + ASSERT_TRUE(bn->get_output_partial_shape(0).same_scheme( + PartialShape{64, 3, Dimension::dynamic(), 224})); +} + +TYPED_TEST_P(BatchNormTest, batch_norm_inference_invalid_inputs_element_types) +{ + PartialShape data_batch_shape{10, 100}; + + const std::vector inputs_et{ + element::i32, + element::u32, + element::boolean + }; + + double eps = 0.001; + + std::vector bn_tests; + for (const auto& et : inputs_et) + { + std::vector ch_inputs = + { + {et, PartialShape{100}, "gamma"}, + {et, PartialShape{100}, "beta"}, + {et, PartialShape{100}, "mean"}, + {et, PartialShape{100}, "variance"} + }; + + bn_tests.push_back(BatchNormInferParams{et, data_batch_shape, ch_inputs, eps}); + } + + for(const auto& params : bn_tests) + { + try + { + auto bn = makeBatchNormOp(params); + FAIL() << "Invalid input element types not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Input element types must be floating-point"); + } + catch (...) + { + FAIL() << "Input element types check failed for unexpected reason"; + } + } +} + +TYPED_TEST_P(BatchNormTest, batch_norm_inference_incompatible_inputs_element_types) +{ + // Data batch input element type and shape + const element::Type data_batch_et = element::f32; + const PartialShape data_batch_ps{10, 200}; + + // Invalid combination of element types of gamma/beta/mean/variance inputs + vector bn_ch_inputs = + { + {element::f32, PartialShape{200}, "gamma"}, + {element::f32, PartialShape{200}, "beta"}, + {element::f32, PartialShape{200}, "mean"}, + {element::f32, PartialShape{200}, "variance"} + }; + + const double epsilon = 0.001; + + std::vector bn_params; + bn_params.push_back(BatchNormInferParams{element::f16, + data_batch_ps, + bn_ch_inputs, + epsilon}); + + for(size_t i = 0; i < bn_ch_inputs.size(); i++) + { + std::vector inputs = bn_ch_inputs; + (inputs[i]).in_et = element::f16; + bn_params.push_back(BatchNormInferParams{data_batch_et, + data_batch_ps, + inputs, + epsilon}); + } + + // Run tests with incompatible input element types + for(const auto& bn_p : bn_params) + { + try + { + auto bn = makeBatchNormOp(bn_p); + FAIL() << "Incompatible input element types not detected"; + } + catch(const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Input element types do not match"); + } + catch(...) + { + FAIL() << "Input element types check failed for unexpected reason"; + } + } +} + +TYPED_TEST_P(BatchNormTest, batch_norm_inference_invalid_data_batch_input_rank) +{ + PartialShape data_batch_shape{Dimension::dynamic()}; + element::Type inputs_et = element::f32; + + std::vector ch_inputs = + { + {inputs_et, PartialShape::dynamic(), "gamma"}, + {inputs_et, PartialShape::dynamic(), "beta"}, + {inputs_et, PartialShape::dynamic(), "mean"}, + {inputs_et, PartialShape::dynamic(), "variance"} + }; + + double epsilon = 0.001; + + const BatchNormInferParams params{inputs_et, data_batch_shape, ch_inputs, epsilon}; try { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Wrong gamma/beta/mean/variance shape not detected"; + auto bn = makeBatchNormOp(params); + FAIL() << "Data batch input with invalid rank 1 not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Input argument must have rank of at least 2 (input argument shape: {?})"); + } + catch (...) + { + FAIL() << "Data batch input rank check failed for unexpected reason"; + } +} + +TYPED_TEST_P(BatchNormTest, batch_norm_inference_incompatible_channel_input_ranks) +{ + PartialShape data_batch_shape{PartialShape::dynamic()}; + element::Type input_et = element::f32; + + std::vector inputs = + { + {input_et, PartialShape{3, Dimension::dynamic()}, "gamma"}, + {input_et, PartialShape::dynamic(), "beta"}, + {input_et, PartialShape{Dimension::dynamic()}, "mean"}, + {input_et, PartialShape::dynamic(), "variance"} + }; + + double epsilon = 0.001; + + const BatchNormInferParams params{input_et, data_batch_shape, inputs, epsilon}; + try + { + auto bn = makeBatchNormOp(params); + FAIL() << "Incompatible gamma/beta/mean/variance input ranks not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Shapes for gamma/beta/mean/variance do not match"); + } + catch (...) + { + FAIL() << "gamma/beta/mean/variance input ranks check failed for unexpected reason"; + } +} + +TYPED_TEST_P(BatchNormTest, + batch_norm_inference_incompatible_channel_inputs_channel_count) +{ + PartialShape data_batch_shape{PartialShape::dynamic()}; + element::Type input_et = element::f32; + + std::vector inputs = + { + {input_et, PartialShape{3}, "gamma"}, + {input_et, PartialShape::dynamic(), "beta"}, + {input_et, PartialShape{4}, "mean"}, + {input_et, PartialShape::dynamic(), "variance"} + }; + + double epsilon = 0.001; + + const BatchNormInferParams params{input_et, data_batch_shape, inputs, epsilon}; + try + { + auto bn = makeBatchNormOp(params); + FAIL() << "Incompatible gamma/beta/mean/variance inputs channel count not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Shapes for gamma/beta/mean/variance do not match"); + } + catch (...) + { + FAIL() << "gamma/beta/mean/variance inputs channel count check failed for unexpected reason"; + } +} + +TYPED_TEST_P(BatchNormTest, batch_norm_inference_invalid_channel_inputs_rank) +{ + PartialShape data_batch_shape{PartialShape::dynamic()}; + element::Type input_et = element::f32; + + std::vector inputs = + { + {input_et, PartialShape{Dimension::dynamic(), Dimension::dynamic()}, "gamma"}, + {input_et, PartialShape::dynamic(), "beta"}, + {input_et, PartialShape{Dimension::dynamic(), Dimension::dynamic()}, "mean"}, + {input_et, PartialShape::dynamic(), "variance"} + }; + + double epsilon = 0.001; + + const BatchNormInferParams params{input_et, data_batch_shape, inputs, epsilon}; + try + { + auto bn = makeBatchNormOp(params); + FAIL() << "Invalid rank of gamma/beta/mean/variance inputs not detected"; } catch (const NodeValidationFailure& error) { EXPECT_HAS_SUBSTRING( error.what(), - std::string("Shape for gamma/beta/mean/variance ({?,?}) does not have rank 1")); + "Shape for gamma/beta/mean/variance ({?,?}) does not have rank 1"); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "gamma/beta/mean/variance inputs rank check failed for unexpected reason"; } } -TEST(type_prop, - batch_norm_inference_partial_input_rank_dynamic_some_rank_static_dynamic_inconsistent_rank) -{ - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{3, Dimension::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{Dimension::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - try - { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Inconsistent gamma/beta/mean/variance shape not detected"; - } - catch (const NodeValidationFailure& error) - { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("Shapes for gamma/beta/mean/variance do not match")); - } - catch (...) - { - FAIL() << "Deduced type check failed for unexpected reason"; - } -} - -TEST(type_prop, - batch_norm_inference_partial_input_rank_dynamic_some_static_inconsistent_channel_count) -{ - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{3}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{4}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - try - { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Inconsistent gamma/beta/mean/variance channel count not detected"; - } - catch (const NodeValidationFailure& error) - { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("Shapes for gamma/beta/mean/variance do not match")); - } - catch (...) - { - FAIL() << "Deduced type check failed for unexpected reason"; - } -} - -TEST(type_prop, batch_norm_inference_partial_input_rank_static_dynamic_some_static_ok) -{ - PartialShape data_batch_shape{64, Dimension::dynamic(), Dimension::dynamic(), 224}; - PartialShape gamma_shape{3}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{3}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - auto bn = - make_shared(data_batch, gamma, beta, mean, variance, epsilon); - - ASSERT_EQ(bn->get_output_size(), 1); - ASSERT_EQ(bn->get_output_element_type(0), data_batch_et); - ASSERT_TRUE(bn->get_output_partial_shape(0).same_scheme( - PartialShape{64, 3, Dimension::dynamic(), 224})); -} - -TEST(type_prop, - batch_norm_inference_partial_input_rank_static_dynamic_some_static_inconsistent_channel_count) +TYPED_TEST_P(BatchNormTest, + batch_norm_inference_incompatible_data_batch_and_channel_inputs_channel_count) { PartialShape data_batch_shape{64, 4, Dimension::dynamic(), 224}; - PartialShape gamma_shape{3}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{3}; - PartialShape variance_shape{PartialShape::dynamic()}; + element::Type input_et = element::f32; + + std::vector inputs = + { + {input_et, PartialShape{3}, "gamma"}, + {input_et, PartialShape::dynamic(), "beta"}, + {input_et, PartialShape{3}, "mean"}, + {input_et, PartialShape::dynamic(), "variance"} + }; + double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); + const BatchNormInferParams params{input_et, data_batch_shape, inputs, epsilon}; try { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Inconsistent input/gamma/beta/mean/variance channel count not detected"; + auto bn = makeBatchNormOp(params); + FAIL() << "Incompatible data batch and gamma/beta/mean/variance channel count not detected"; } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("Input channel dimension (4) does not match " - "shape for gamma/beta/mean/variance ({3})")); + EXPECT_HAS_SUBSTRING(error.what(), "Input channel dimension (4) does not match " + "shape for gamma/beta/mean/variance ({3})"); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Data batch and gamma/beta/mean/variance channel count check failed for unexpected reason"; } } -TEST(type_prop, batch_norm_inference_partial_all_rank_dynamic_v5) -{ - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{PartialShape::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{PartialShape::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - auto bn = - make_shared(data_batch, gamma, beta, mean, variance, epsilon); - - ASSERT_EQ(bn->get_output_size(), 1); - ASSERT_EQ(bn->get_output_element_type(0), data_batch_et); - ASSERT_TRUE(bn->get_output_partial_shape(0).rank().is_dynamic()); -} - -TEST(type_prop, batch_norm_inference_partial_input_rank_static_dynamic_ok_v5) -{ - PartialShape data_batch_shape{ - 64, Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}; - PartialShape gamma_shape{PartialShape::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{PartialShape::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - auto bn = - make_shared(data_batch, gamma, beta, mean, variance, epsilon); - - ASSERT_EQ(bn->get_output_size(), 1); - ASSERT_EQ(bn->get_output_element_type(0), data_batch_et); - ASSERT_TRUE(bn->get_output_partial_shape(0).same_scheme( - PartialShape{64, Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()})); -} - -TEST(type_prop, batch_norm_inference_partial_input_rank_static_dynamic_zero_channels_v5) +TYPED_TEST_P(BatchNormTest, batch_norm_inference_invalid_input_channels_count_zero) { PartialShape data_batch_shape{ Dimension::dynamic(), 0, Dimension::dynamic(), Dimension::dynamic()}; - PartialShape gamma_shape{PartialShape::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{PartialShape::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; + element::Type inputs_et = element::f32; + + std::vector ch_inputs = + { + {inputs_et, PartialShape::dynamic(), "gamma"}, + {inputs_et, PartialShape::dynamic(), "beta"}, + {inputs_et, PartialShape::dynamic(), "mean"}, + {inputs_et, PartialShape::dynamic(), "variance"} + }; + double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - + + const BatchNormInferParams params{inputs_et, data_batch_shape, ch_inputs, epsilon}; try { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Zero channel count not detected"; + auto bn = makeBatchNormOp(params); + FAIL() << "Data batch channel count zero not detected"; } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Channel count must be at least 1")); + EXPECT_HAS_SUBSTRING(error.what(), "Channel count must be at least 1"); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Data batch channel count check failed for unexpected reason"; } } -TEST(type_prop, batch_norm_inference_partial_input_rank_dynamic_some_rank_static_dynamic_ok_v5) +TYPED_TEST_P(BatchNormTest, batch_norm_inference_invalid_epsilon) { - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{Dimension::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{Dimension::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; + PartialShape data_batch_shape{10, 100}; + element::Type inputs_et = element::f32; - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - auto bn = - make_shared(data_batch, gamma, beta, mean, variance, epsilon); - - ASSERT_EQ(bn->get_output_size(), 1); - ASSERT_EQ(bn->get_output_element_type(0), data_batch_et); - ASSERT_TRUE(bn->get_output_partial_shape(0).rank().is_dynamic()); -} - -TEST(type_prop, - batch_norm_inference_partial_input_rank_dynamic_some_rank_static_dynamic_wrong_rank_v5) -{ - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{Dimension::dynamic(), Dimension::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{Dimension::dynamic(), Dimension::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - try + std::vector ch_inputs = { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Wrong gamma/beta/mean/variance shape not detected"; - } - catch (const NodeValidationFailure& error) + {inputs_et, PartialShape{100}, "gamma"}, + {inputs_et, PartialShape{100}, "beta"}, + {inputs_et, PartialShape{100}, "mean"}, + {inputs_et, PartialShape{100}, "variance"} + }; + + double eps_zero = 0.0; + double eps_neg = -1.0; + + const std::vector bn_tests{ + BatchNormInferParams{inputs_et, data_batch_shape, ch_inputs, eps_zero}, + BatchNormInferParams{inputs_et, data_batch_shape, ch_inputs, eps_neg} + }; + + for(const auto& params : bn_tests) { - EXPECT_HAS_SUBSTRING( - error.what(), - std::string("Shape for gamma/beta/mean/variance ({?,?}) does not have rank 1")); - } - catch (...) - { - FAIL() << "Deduced type check failed for unexpected reason"; + try + { + auto bn = makeBatchNormOp(params); + FAIL() << "Invalid 'epsilon' attribute value not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "Attribute 'epsilon' must have non-zero positive floating-point value."); + } + catch (...) + { + FAIL() << "Positive 'epsilon' attribute value check failed for unexpected reason"; + } } } -TEST(type_prop, - batch_norm_inference_partial_input_rank_dynamic_some_rank_static_dynamic_inconsistent_rank_v5) -{ - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{3, Dimension::dynamic()}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{Dimension::dynamic()}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; +REGISTER_TYPED_TEST_CASE_P( + BatchNormTest, + batch_norm_inference_basic_data_batch_rank_2, + batch_norm_inference_basic_data_batch_rank_4, + batch_norm_inference_inputs_rank_dynamic, + batch_norm_inference_data_batch_rank_static_channel_inputs_rank_dynamic, + batch_norm_inference_data_batch_rank_dynamic_some_channel_inputs_rank_static, + batch_norm_inference_data_batch_rank_static_some_channel_inputs_rank_static, + batch_norm_inference_invalid_inputs_element_types, + batch_norm_inference_incompatible_inputs_element_types, + batch_norm_inference_invalid_data_batch_input_rank, + batch_norm_inference_incompatible_channel_input_ranks, + batch_norm_inference_incompatible_channel_inputs_channel_count, + batch_norm_inference_invalid_channel_inputs_rank, + batch_norm_inference_incompatible_data_batch_and_channel_inputs_channel_count, + batch_norm_inference_invalid_input_channels_count_zero, + batch_norm_inference_invalid_epsilon); - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - try - { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Inconsistent gamma/beta/mean/variance shape not detected"; - } - catch (const NodeValidationFailure& error) - { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("Shapes for gamma/beta/mean/variance do not match")); - } - catch (...) - { - FAIL() << "Deduced type check failed for unexpected reason"; - } -} - -TEST(type_prop, - batch_norm_inference_partial_input_rank_dynamic_some_static_inconsistent_channel_count_v5) -{ - PartialShape data_batch_shape{PartialShape::dynamic()}; - PartialShape gamma_shape{3}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{4}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - try - { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Inconsistent gamma/beta/mean/variance channel count not detected"; - } - catch (const NodeValidationFailure& error) - { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("Shapes for gamma/beta/mean/variance do not match")); - } - catch (...) - { - FAIL() << "Deduced type check failed for unexpected reason"; - } -} - -TEST(type_prop, batch_norm_inference_partial_input_rank_static_dynamic_some_static_ok_v5) -{ - PartialShape data_batch_shape{64, Dimension::dynamic(), Dimension::dynamic(), 224}; - PartialShape gamma_shape{3}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{3}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - auto bn = - make_shared(data_batch, gamma, beta, mean, variance, epsilon); - - ASSERT_EQ(bn->get_output_size(), 1); - ASSERT_EQ(bn->get_output_element_type(0), data_batch_et); - ASSERT_TRUE(bn->get_output_partial_shape(0).same_scheme( - PartialShape{64, 3, Dimension::dynamic(), 224})); -} - -TEST( - type_prop, - batch_norm_inference_partial_input_rank_static_dynamic_some_static_inconsistent_channel_count_v5) -{ - PartialShape data_batch_shape{64, 4, Dimension::dynamic(), 224}; - PartialShape gamma_shape{3}; - PartialShape beta_shape{PartialShape::dynamic()}; - PartialShape mean_shape{3}; - PartialShape variance_shape{PartialShape::dynamic()}; - double epsilon = 0.001; - element::Type data_batch_et = element::f32; - element::Type gamma_et = element::f32; - element::Type beta_et = element::f32; - element::Type mean_et = element::f32; - element::Type variance_et = element::f32; - - auto data_batch = make_shared(data_batch_et, data_batch_shape); - auto gamma = make_shared(gamma_et, gamma_shape); - auto beta = make_shared(beta_et, beta_shape); - auto mean = make_shared(mean_et, mean_shape); - auto variance = make_shared(variance_et, variance_shape); - - try - { - auto bn = make_shared( - data_batch, gamma, beta, mean, variance, epsilon); - FAIL() << "Inconsistent input/gamma/beta/mean/variance channel count not detected"; - } - catch (const NodeValidationFailure& error) - { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("Input channel dimension (4) does not match " - "shape for gamma/beta/mean/variance ({3})")); - } - catch (...) - { - FAIL() << "Deduced type check failed for unexpected reason"; - } -} +using Types = ::testing::Types; +INSTANTIATE_TYPED_TEST_CASE_P(type_prop, BatchNormTest, Types, ); diff --git a/ngraph/test/visitors/op/batch_norm.cpp b/ngraph/test/visitors/op/batch_norm.cpp new file mode 100644 index 00000000000..9f5e6e0bda2 --- /dev/null +++ b/ngraph/test/visitors/op/batch_norm.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#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; + +template +class BatchNormAttrTest : public ::testing::Test +{ +}; + +TYPED_TEST_CASE_P(BatchNormAttrTest); + +TYPED_TEST_P(BatchNormAttrTest, batch_norm_inference_op) +{ + PartialShape in_shape{1, 10}; + PartialShape ch_shape{in_shape[1]}; + element::Type et = element::f32; + double epsilon = 0.001; + + NodeBuilder::get_ops().register_factory(); + auto data_batch = make_shared(et, in_shape); + auto gamma = make_shared(et, ch_shape); + auto beta = make_shared(et, ch_shape); + auto mean = make_shared(et, ch_shape); + auto var = make_shared(et, ch_shape); + auto batch_norm = make_shared(data_batch, gamma, beta, mean, var, epsilon); + + const auto expected_attr_count = 1; + NodeBuilder builder(batch_norm); + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); + auto g_batch_norm = as_type_ptr(builder.create()); + EXPECT_EQ(g_batch_norm->get_eps_value(), batch_norm->get_eps_value()); +} + +REGISTER_TYPED_TEST_CASE_P( + BatchNormAttrTest, + batch_norm_inference_op); + +using Types = ::testing::Types; + +INSTANTIATE_TYPED_TEST_CASE_P(attributes, BatchNormAttrTest, Types); From f458bd4384ef251e8d440f4d172fd49f9f4a30bc Mon Sep 17 00:00:00 2001 From: Sergey Shlyapnikov Date: Wed, 12 May 2021 13:56:12 +0300 Subject: [PATCH 29/99] [IE CLDNN] Disable CoreThreadingTestsWithIterations test skipping (#5495) --- .../plugin/gpu/shared_tests_instances/skip_tests_config.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp index a9e6a6aeac0..8cad5eddcd3 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp @@ -11,8 +11,6 @@ std::vector disabledTestPatterns() { return { //TODO: Issue: 34748 R"(.*(ComparisonLayerTest).*)", - // TODO: Issue: 39014 - R"(.*CoreThreadingTestsWithIterations.*smoke_LoadNetwork.*)", // TODO: Issue: 39612 R"(.*Interpolate.*cubic.*tf_half_pixel_for_nn.*FP16.*)", // Expected behavior From abd663463d0601fbf1281ebae063b5e69b09bc69 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 12 May 2021 14:17:43 +0300 Subject: [PATCH 30/99] Mak SO objct to be mandatory argument for VariablState (#5572) --- inference-engine/include/cpp/ie_executable_network.hpp | 4 ++-- inference-engine/include/cpp/ie_infer_request.hpp | 4 ++-- inference-engine/include/cpp/ie_memory_state.hpp | 9 +++++---- .../src/inference_engine/cpp/ie_variable_state.cpp | 7 ++++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/inference-engine/include/cpp/ie_executable_network.hpp b/inference-engine/include/cpp/ie_executable_network.hpp index 6f686699754..1001e65903d 100644 --- a/inference-engine/include/cpp/ie_executable_network.hpp +++ b/inference-engine/include/cpp/ie_executable_network.hpp @@ -35,8 +35,8 @@ class INFERENCE_ENGINE_API_CLASS(ExecutableNetwork) { std::shared_ptr _impl; std::shared_ptr _so; - explicit ExecutableNetwork(const std::shared_ptr& impl, - const std::shared_ptr& so); + ExecutableNetwork(const std::shared_ptr& impl, + const std::shared_ptr& so); friend class InferencePlugin; diff --git a/inference-engine/include/cpp/ie_infer_request.hpp b/inference-engine/include/cpp/ie_infer_request.hpp index 4ca0e59335d..8ae8f1be3b9 100644 --- a/inference-engine/include/cpp/ie_infer_request.hpp +++ b/inference-engine/include/cpp/ie_infer_request.hpp @@ -36,8 +36,8 @@ class INFERENCE_ENGINE_API_CLASS(InferRequest) { std::shared_ptr _impl; std::shared_ptr _so; - explicit InferRequest(const std::shared_ptr& impl, - const std::shared_ptr& so); + InferRequest(const std::shared_ptr& impl, + const std::shared_ptr& so); friend class ExecutableNetwork; diff --git a/inference-engine/include/cpp/ie_memory_state.hpp b/inference-engine/include/cpp/ie_memory_state.hpp index 5baecc2de5c..6907862efc1 100644 --- a/inference-engine/include/cpp/ie_memory_state.hpp +++ b/inference-engine/include/cpp/ie_memory_state.hpp @@ -11,9 +11,10 @@ #pragma once #include +#include +#include "ie_api.h" #include "ie_blob.h" -#include "details/ie_so_loader.h" namespace InferenceEngine { @@ -28,15 +29,15 @@ class IVariableStateInternal; */ class INFERENCE_ENGINE_API_CLASS(VariableState) { std::shared_ptr _impl = nullptr; - details::SharedObjectLoader::Ptr _so = nullptr; + std::shared_ptr _so = nullptr; /** * @brief Constructs VariableState from the initialized std::shared_ptr * @param impl Initialized shared pointer * @param so Optional: Plugin to use. This is required to ensure that VariableState can work properly even if plugin object is destroyed. */ - explicit VariableState(const std::shared_ptr& impl, - const details::SharedObjectLoader::Ptr& so = {}); + VariableState(const std::shared_ptr& impl, + const std::shared_ptr& so); friend class InferRequest; friend class ExecutableNetwork; diff --git a/inference-engine/src/inference_engine/cpp/ie_variable_state.cpp b/inference-engine/src/inference_engine/cpp/ie_variable_state.cpp index b50a03beb96..5d4a09dcb5d 100644 --- a/inference-engine/src/inference_engine/cpp/ie_variable_state.cpp +++ b/inference-engine/src/inference_engine/cpp/ie_variable_state.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // +#include "details/ie_so_loader.h" #include "cpp/ie_memory_state.hpp" #include "cpp_interfaces/interface/ie_ivariable_state_internal.hpp" #include "exception2status.hpp" @@ -18,8 +19,8 @@ namespace InferenceEngine { -VariableState::VariableState(const std::shared_ptr& impl, - const details::SharedObjectLoader::Ptr& so) : _impl(impl), _so(so) { +VariableState::VariableState(const std::shared_ptr& impl, + const std::shared_ptr& so) : _impl(impl), _so(so) { if (impl == nullptr) { IE_THROW(NotAllocated) << "VariableState wrapper was not initialized."; } @@ -49,4 +50,4 @@ void VariableState::SetState(Blob::Ptr state) { VARIABLE_CALL_STATEMENT(_impl->SetState(state)); } -} // namespace InferenceEngine \ No newline at end of file +} // namespace InferenceEngine From 2ba5c344bec165a03216312b9f5bcca9bcd36053 Mon Sep 17 00:00:00 2001 From: Jozef Daniecki Date: Wed, 12 May 2021 13:35:12 +0200 Subject: [PATCH 31/99] Add unit tests for Convert operation (#5558) * Add Serialization SLT for Convert op. * Add comment with explanaition to convert ref impl. * Refactored backend tests for Convert operation. * Give better names to backend tests. * Add more backend unit tests. * Fixed tests related to u1/u4/i4 types. --- .../serialization/single_layer/convert.cpp | 37 ++ .../ngraph/runtime/reference/convert.hpp | 1 + ngraph/core/src/op/convert.cpp | 17 + ngraph/test/backend/convert.in.cpp | 483 ++++++++++++++---- ngraph/test/runtime/ie/unit_test.manifest | 22 +- 5 files changed, 454 insertions(+), 106 deletions(-) create mode 100644 inference-engine/tests/functional/inference_engine/serialization/single_layer/convert.cpp diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/convert.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/convert.cpp new file mode 100644 index 00000000000..c56d444dcdc --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/convert.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/single_layer/convert.hpp" + +#include + +using namespace LayerTestsDefinitions; + +namespace { +const std::vector> inShape = {{1, 2, 3, 4}}; + +const std::vector precisions = { + InferenceEngine::Precision::BOOL, InferenceEngine::Precision::U8, + InferenceEngine::Precision::I8, InferenceEngine::Precision::U16, + InferenceEngine::Precision::I16, InferenceEngine::Precision::U32, + InferenceEngine::Precision::I32, InferenceEngine::Precision::U64, + InferenceEngine::Precision::I64, InferenceEngine::Precision::BF16, + InferenceEngine::Precision::FP16, InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP64}; + +TEST_P(ConvertLayerTest, Serialize) { + Serialize(); +} + +INSTANTIATE_TEST_CASE_P( + smoke_Serialization_ConvertLayerTest, ConvertLayerTest, + ::testing::Combine(::testing::Values(inShape), + ::testing::ValuesIn(precisions), + ::testing::ValuesIn(precisions), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ConvertLayerTest::getTestCaseName); + +} // namespace \ No newline at end of file diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/convert.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/convert.hpp index 0374cb18da0..8591f88c794 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/convert.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/convert.hpp @@ -29,6 +29,7 @@ namespace ngraph template <> void convert(const float16* arg, float* out, size_t count); + // overload to handle ngraph::boolean (it is stored as char) template typename std::enable_if::value>::type convert(const TI* arg, TO* out, size_t count) diff --git a/ngraph/core/src/op/convert.cpp b/ngraph/core/src/op/convert.cpp index 47ce6907322..8999113ba08 100644 --- a/ngraph/core/src/op/convert.cpp +++ b/ngraph/core/src/op/convert.cpp @@ -26,6 +26,23 @@ op::Convert::Convert(const Output& arg, const element::Type& destination_t void op::Convert::validate_and_infer_types() { NGRAPH_OP_SCOPE(v0_Convert_validate_and_infer_types); + const element::Type data_et = get_input_element_type(0); + const element::Type destination_et = m_destination_type; + + NODE_VALIDATION_CHECK(this, + data_et != element::u1 && data_et != element::u4 && + data_et != element::i4, + "Input element type '", + data_et, + "' is not supported."); + + NODE_VALIDATION_CHECK(this, + destination_et != element::u1 && destination_et != element::u4 && + destination_et != element::i4, + "Destination element type '", + destination_et, + "' is not supported."); + set_output_type(0, m_destination_type, get_input_partial_shape(0)); } diff --git a/ngraph/test/backend/convert.in.cpp b/ngraph/test/backend/convert.in.cpp index ab9f33c6743..46159d0cbc2 100644 --- a/ngraph/test/backend/convert.in.cpp +++ b/ngraph/test/backend/convert.in.cpp @@ -21,138 +21,421 @@ using namespace ngraph; static string s_manifest = "${MANIFEST}"; using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); - -NGRAPH_TEST(${BACKEND_NAME}, convert_int32_float32) +namespace { - Shape shape{2, 2}; - auto A = make_shared(element::i32, shape); - auto f = make_shared(make_shared(A, element::f32), ParameterVector{A}); + template + void ConvertTest(const std::vector& input, + const Shape& input_shape, + const ngraph::element::Type& input_type, + const std::vector& expected_output, + const ngraph::element::Type& expected_output_type) + { + const auto in = make_shared(input_type, input_shape); + const auto convert = make_shared(in, expected_output_type); + const auto f = make_shared(NodeVector{convert}, ParameterVector{in}); - auto backend = runtime::Backend::create("${BACKEND_NAME}"); + auto test_case = test::TestCase(f); + test_case.add_input(input); + test_case.add_expected_output(expected_output); - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape); - copy_data(a, vector{281, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, shape); + test_case.run(); + } +} // namespace - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{281, 2, 3, 4}), read_vector(result))); +// destination: boolean +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_boolean) +{ + const uint8_t lowest = std::numeric_limits::lowest(); + const uint8_t max = std::numeric_limits::max(); + + const std::vector input{0, 12, 23, 0, lowest, max}; + const Shape input_shape{2, 3}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 1, 1, 0, 0, 1}; + const element::Type expected_output_type = ngraph::element::boolean; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); } -NGRAPH_TEST(${BACKEND_NAME}, convert_uint16_float32) +NGRAPH_TEST(${BACKEND_NAME}, convert_i32_to_boolean) { - Shape shape{2, 2}; - auto A = make_shared(element::u16, shape); - auto f = make_shared(make_shared(A, element::f32), ParameterVector{A}); + const int32_t lowest = std::numeric_limits::lowest(); + const int32_t max = std::numeric_limits::max(); - auto backend = runtime::Backend::create("${BACKEND_NAME}"); + const std::vector input{0, -12, 23, 0, lowest, max}; + const Shape input_shape{2, 3}; + const element::Type input_type = ngraph::element::i32; - // Create some tensors for input/output - auto a = backend->create_tensor(element::u16, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, shape); + const std::vector expected_output{0, 1, 1, 0, 1, 1}; + const element::Type expected_output_type = ngraph::element::boolean; - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f( - (vector{1, 2, 3, 4}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); } -NGRAPH_TEST(${BACKEND_NAME}, convert_int32_bool) +NGRAPH_TEST(${BACKEND_NAME}, convert_f32_to_boolean) { - Shape shape{2, 3}; - auto A = make_shared(element::i32, shape); - auto f = - make_shared(make_shared(A, element::boolean), ParameterVector{A}); + const float lowest = std::numeric_limits::lowest(); + const float max = std::numeric_limits::max(); + const float min = std::numeric_limits::min(); + const float pos_inf = std::numeric_limits::infinity(); + const float neg_inf = -std::numeric_limits::infinity(); - auto backend = runtime::Backend::create("${BACKEND_NAME}"); + const std::vector input{0.f, 1.5745f, 0.12352f, 0.f, lowest, max, min, pos_inf, neg_inf}; + const Shape input_shape{3, 3}; + const element::Type input_type = ngraph::element::f32; - int32_t lowest = std::numeric_limits::lowest(); - int32_t max = std::numeric_limits::max(); + const std::vector expected_output{0, 1, 1, 0, 1, 1, 1, 1, 1}; + const element::Type expected_output_type = ngraph::element::boolean; - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape); - copy_data(a, vector{0, 12, 23, 0, lowest, max}); - auto result = backend->create_tensor(element::boolean, shape); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{0, 1, 1, 0, 1, 1}), read_vector(result)); + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); } -NGRAPH_TEST(${BACKEND_NAME}, convert_float32_bool) +// destination: bf16 +NGRAPH_TEST(${BACKEND_NAME}, convert_f32_to_bf16) { - Shape shape{3, 3}; - auto A = make_shared(element::f32, shape); - auto f = - make_shared(make_shared(A, element::boolean), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - float lowest = std::numeric_limits::lowest(); - float max = std::numeric_limits::max(); - float min = std::numeric_limits::min(); - float pos_inf = std::numeric_limits::infinity(); - float neg_inf = -std::numeric_limits::infinity(); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{0.f, 1.5745f, 0.12352f, 0.f, lowest, max, min, pos_inf, neg_inf}); - auto result = backend->create_tensor(element::boolean, shape); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{0, 1, 1, 0, 1, 1, 1, 1, 1}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, convert_float32_bf16) -{ - const vector a_data = { + const std::vector input{ 0.5f, 1.5f, 0.5f, 2.5f, 1.5f, 0.5f, 3.5f, 2.5f, 0.5f, 0.5f, 2.5f, 0.5f, 0.5f, 0.5f, 1.5f}; + const Shape input_shape{1, 1, 3, 5}; + const element::Type input_type = ngraph::element::f32; - const auto A = make_shared(element::f32, Shape{1, 1, 3, 5}); - const auto convert = make_shared(A, element::bf16); - const auto f = make_shared(NodeVector{convert}, ParameterVector{A}); + const std::vector expected_output(std::begin(input), std::end(input)); + const element::Type expected_output_type = ngraph::element::bf16; - auto test_case = test::TestCase(f); - test_case.add_input(a_data); - test_case.add_expected_output( - std::vector(std::begin(a_data), std::end(a_data))); - - test_case.run(); + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); } -NGRAPH_TEST(${BACKEND_NAME}, convert_bf16_float32) +// destination: f16 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_f16) { - const vector a_data = { + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; + const element::Type expected_output_type = ngraph::element::f16; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: f32 +NGRAPH_TEST(${BACKEND_NAME}, convert_i4_to_f32_is_not_supported_yet) +{ + const std::vector input{0x00, 0x00}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::i4; + + const std::vector expected_output{0.0f, 0.0f, 0.0f, 0.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ASSERT_THROW(ConvertTest(input, input_shape, input_type, expected_output, expected_output_type), + ngraph::NodeValidationFailure); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_i8_to_f32) +{ + const std::vector input{-127, -0, 0, 127}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::i8; + + const std::vector expected_output{-127.0f, -0.0f, 0.0f, 127.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_i16_to_f32) +{ + const std::vector input{-32000, -0, 0, 32000}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::i16; + + const std::vector expected_output{-32000.0f, -0.0f, 0.0f, 32000.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_i32_to_f32) +{ + const std::vector input{-64000, -0, 0, 64000}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::i32; + + const std::vector expected_output{-64000.0f, -0.0f, 0.0f, 64000.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_i64_to_f32) +{ + const std::vector input{-64000, -0, 0, 64000}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::i64; + + const std::vector expected_output{-64000.0f, -0.0f, 0.0f, 64000.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_u1_to_f32_is_not_supported_yet) +{ + const std::vector input{0x00}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::u1; + + const std::vector expected_output{0.0f, 0.0f, 0.0f, 0.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ASSERT_THROW(ConvertTest(input, input_shape, input_type, expected_output, expected_output_type), + ngraph::NodeValidationFailure); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_u4_to_f32_is_not_supported_yet) +{ + const std::vector input{0x00, 0x00}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::u4; + + const std::vector expected_output{0.0f, 0.0f, 0.0f, 0.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ASSERT_THROW(ConvertTest(input, input_shape, input_type, expected_output, expected_output_type), + ngraph::NodeValidationFailure); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_f32) +{ + const std::vector input{255, 128, 32, 0}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{255.0f, 128.0f, 32.0f, 0.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_u16_to_f32) +{ + const std::vector input{64000, 32000, 128, 0}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::u16; + + const std::vector expected_output{64000.0f, 32000.0f, 128.0f, 0.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_u32_to_f32) +{ + const std::vector input{4000000, 2000000, 128, 0}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::u32; + + const std::vector expected_output{4000000.0f, 2000000.0f, 128.0f, 0.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_u64_to_f32) +{ + const std::vector input{4000000, 2000000, 128, 0}; + const Shape input_shape{2, 2}; + const element::Type input_type = ngraph::element::u64; + + const std::vector expected_output{4000000.0f, 2000000.0f, 128.0f, 0.0f}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_bf16_to_f32) +{ + const std::vector input{ 0.5, 1.5, 0.5, 2.5, 1.5, 0.5, 3.5, 2.5, 0.5, 0.5, 2.5, 0.5, 0.5, 0.5, 1.5}; + const Shape input_shape{1, 1, 3, 5}; + const element::Type input_type = ngraph::element::bf16; - const auto A = make_shared(element::bf16, Shape{1, 1, 3, 5}); - const auto convert = make_shared(A, element::f32); - const auto f = make_shared(NodeVector{convert}, ParameterVector{A}); + const std::vector expected_output(std::begin(input), std::end(input)); + const element::Type expected_output_type = ngraph::element::f32; - auto test_case = test::TestCase(f); - test_case.add_input(a_data); - test_case.add_expected_output(std::vector(std::begin(a_data), std::end(a_data))); - - test_case.run(); + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); } -NGRAPH_TEST(${BACKEND_NAME}, convert_fp16_float32) +NGRAPH_TEST(${BACKEND_NAME}, convert_f16_to_f32) { - std::vector f32vec = {-20.5, -15, -10.5, -0.5, 0, 0.5, 10.5, 15, 20.5}; - std::vector f16vec(std::begin(f32vec), std::end(f32vec)); - std::vector result(f32vec.size()); - runtime::reference::convert(f16vec.data(), result.data(), f32vec.size()); - EXPECT_EQ(result, f32vec); + const std::vector input{-20.5, -15, -10.5, -0.5, 0, 0.5, 10.5, 15, 20.5}; + const Shape input_shape{3, 3}; + const element::Type input_type = ngraph::element::f16; + + const std::vector expected_output{-20.5, -15, -10.5, -0.5, 0, 0.5, 10.5, 15, 20.5}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); } -NGRAPH_TEST(${BACKEND_NAME}, convert_uint8_fp16) +NGRAPH_TEST(${BACKEND_NAME}, convert_f32_to_f32) { - std::vector u8vec = {0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; - std::vector f16vec(std::begin(u8vec), std::end(u8vec)); - std::vector result(u8vec.size()); - runtime::reference::convert(u8vec.data(), result.data(), u8vec.size()); - EXPECT_EQ(result, f16vec); + const std::vector input{-20.5, -15, -10.5, -0.5, 0, 0.5, 10.5, 15, 20.5}; + const Shape input_shape{3, 3}; + const element::Type input_type = ngraph::element::f32; + + const std::vector expected_output{-20.5, -15, -10.5, -0.5, 0, 0.5, 10.5, 15, 20.5}; + const element::Type expected_output_type = ngraph::element::f32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: f64 +// not supported by IE, hence no tests + +// destination: i4 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_i4_is_not_supported_yet) +{ + const std::vector input{0, 0, 0, 0}; + const Shape input_shape{4}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0x00, 0x00}; + const element::Type expected_output_type = ngraph::element::i4; + + ASSERT_THROW(ConvertTest(input, input_shape, input_type, expected_output, expected_output_type), + ngraph::NodeValidationFailure); +} + +// destination: i8 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_i8) +{ + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 128}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const element::Type expected_output_type = ngraph::element::i8; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: i16 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_i16) +{ + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; + const element::Type expected_output_type = ngraph::element::i16; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: i32 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_i32) +{ + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; + const element::Type expected_output_type = ngraph::element::i32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: i64 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_i64) +{ + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 130, 142}; + const element::Type expected_output_type = ngraph::element::i64; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: u1 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_u1_is_not_supported_yet) +{ + const std::vector input{0, 0, 0, 0}; + const Shape input_shape{4}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0x00}; + const element::Type expected_output_type = ngraph::element::u1; + + ASSERT_THROW(ConvertTest(input, input_shape, input_type, expected_output, expected_output_type), + ngraph::NodeValidationFailure); +} + +// destination: u4 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_u4_is_not_supported_yet) +{ + const std::vector input{0, 0, 0, 0}; + const Shape input_shape{4}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0x00, 0x00}; + const element::Type expected_output_type = ngraph::element::u4; + + ASSERT_THROW(ConvertTest(input, input_shape, input_type, expected_output, expected_output_type), + ngraph::NodeValidationFailure); +} + +// destination: u8 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_u8) +{ + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const element::Type expected_output_type = ngraph::element::u8; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: u16 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_u16) +{ + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const element::Type expected_output_type = ngraph::element::u16; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: u32 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_u32) +{ + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const element::Type expected_output_type = ngraph::element::u32; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); +} + +// destination: u64 +NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_u64) +{ + const std::vector input{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const Shape input_shape{11}; + const element::Type input_type = ngraph::element::u8; + + const std::vector expected_output{0, 10, 15, 20, 43, 56, 78, 99, 102, 110, 127}; + const element::Type expected_output_type = ngraph::element::u64; + + ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); } diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index cac9e71d603..9e8bb87ca58 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -53,7 +53,6 @@ onnx_model_addmul_abc IE_CPU.interpolate_down_scales_const_linear # data [] doesn't exist -convert_float32_bool broadcast_trivial aliased_output bool_init_raw @@ -824,9 +823,6 @@ cum_sum_2dim cum_sum_3d cum_sum_2dim_allmodes -# Cannot create MKLDNNMemoryDesc from TensorDesc. Unsupported precision! -convert_uint16_float32 - # Unsupported primitive of type: Ceiling ceiling @@ -886,7 +882,6 @@ strided_slice_stride_optional divide_int32 divide_cpp_rounding_int32 divide_python_rounding_int32 -convert_int32_bool lesseq_int32 # Constant and Low Precision @@ -1056,6 +1051,22 @@ roll_3d_input roll_3d_input_negative_shift roll_negative_axes +# convert operation +IE_CPU.convert_f16_to_f32 +IE_CPU.convert_u8_to_f16 +IE_CPU.convert_u8_to_i16 +IE_CPU.convert_u8_to_i64 +IE_CPU.convert_u8_to_u16 +IE_CPU.convert_u8_to_u32 +IE_CPU.convert_u8_to_u64 +IE_CPU.convert_u8_to_boolean +IE_CPU.convert_i32_to_boolean +IE_CPU.convert_f32_to_boolean +IE_CPU.convert_u32_to_f32 # NOT_IMPLEMENTED +IE_CPU.convert_i4_to_f32 # NOT_IMPLEMENTED +IE_CPU.convert_u1_to_f32 # NOT_IMPLEMENTED +IE_CPU.convert_u4_to_f32 # NOT_IMPLEMENTED + #------------------------------------------------------------------------------- # # Inference Engine CPU plugin excludes @@ -1418,7 +1429,6 @@ IE_GPU.divide_overload IE_GPU.divide_by_zero_float32 IE_GPU.cosh IE_GPU.cos -IE_GPU.convert_int32_float32 IE_GPU.concat_negative_axis IE_GPU.concat_matrix_colwise IE_GPU.concat_matrix_rowwise From 3c9354816300521c0d6ea8af27773a4c3a666e7a Mon Sep 17 00:00:00 2001 From: Nico Galoppo Date: Wed, 12 May 2021 04:35:50 -0700 Subject: [PATCH 32/99] Fix python_tools benchmark installation location (#5539) * Fix python_tools benchmark installation location Before this fix, when running "make install", the benchmark python files would be installed under /openvino/tools, instead of /openvino/tools/benchmark. This commit fixes this. * Alternative implementation --- tools/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index fa573d5b519..51aeebf395b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -45,7 +45,7 @@ if(ENABLE_PYTHON) DESTINATION python/${PYTHON_VERSION}/openvino/tools COMPONENT python_tools_${PYTHON_VERSION}) - install(DIRECTORY benchmark/ + install(DIRECTORY benchmark DESTINATION python/${PYTHON_VERSION}/openvino/tools USE_SOURCE_PERMISSIONS COMPONENT python_tools_${PYTHON_VERSION}) From b5c43d8a7875614d40cd6b2e085f3708fd48ca71 Mon Sep 17 00:00:00 2001 From: Anuj Mittal Date: Wed, 12 May 2021 19:37:23 +0800 Subject: [PATCH 33/99] plugin_api: fix build with gcc 11 (#5546) Some C++ Standard Library headers have been changed in gcc 11 to no longer include other headers that they do need to depend on. Include exception explicitly to avoid: | inference-engine/src/plugin_api/ie_system_conf.h:21:31: error: 'exception_ptr' in namespace 'std' does not name a type; did you mean 'exception'? | 21 | INFERENCE_ENGINE_API_CPP(std::exception_ptr&) CurrentException(); | | ^~~~~~~~~~~~~ Signed-off-by: Anuj Mittal --- inference-engine/src/plugin_api/ie_system_conf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/inference-engine/src/plugin_api/ie_system_conf.h b/inference-engine/src/plugin_api/ie_system_conf.h index 93d633c35f9..28c1e155e87 100644 --- a/inference-engine/src/plugin_api/ie_system_conf.h +++ b/inference-engine/src/plugin_api/ie_system_conf.h @@ -11,6 +11,7 @@ #include "ie_api.h" #include +#include namespace InferenceEngine { From bb943e880ab83f36d90f2c7666d2feaf74174635 Mon Sep 17 00:00:00 2001 From: Irina Efode Date: Wed, 12 May 2021 14:59:29 +0300 Subject: [PATCH 34/99] [IE TESTS] Add util which allow to update skip_test_config for conformance (#5493) --- .../utils/update_skip_test_config.py | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/update_skip_test_config.py diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/update_skip_test_config.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/update_skip_test_config.py new file mode 100644 index 00000000000..81f1c750b96 --- /dev/null +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/update_skip_test_config.py @@ -0,0 +1,86 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import os +import glob +import argparse + + +def parse_arguments(): + parser = argparse.ArgumentParser() + + skip_config_help = "Paths to folder with skip_config_files" + input_folders_help = "Paths to folders with logs" + + parser.add_argument("-s", "--skip_config_folders", help=skip_config_help, nargs='*', required=True) + parser.add_argument("-i", "--input_logs", help=input_folders_help, nargs='*', required=True) + + return parser.parse_args() + + +def is_conformance(content: str): + if 'conformance' in content: + return True + return False + + +def is_hung_test(content: str): + if content == '' or \ + "SKIPPED" in content or \ + "FAILED" in content or \ + "Unexpected application crash!" in content or \ + "PASSED" in content: + return False + return True + + +def get_device_name(content: str): + target_device_str = 'TargetDevice=' + pos_start = content.find(target_device_str) + pos_end = content.find('\n') + return f'{content[pos_start + len(target_device_str):pos_end]}'.lower() + + +def get_regex(content: str): + ir_name_str = 'IR_name=' + pos_start = content.find(ir_name_str) + pos_end = content.find('.xml_') + return f'.*{content[pos_start + len(ir_name_str):pos_end]}.*\n' + + +def get_conformance_hung_test(test_log_dirs: list): + regexp = dict() + for test_log_dir in test_log_dirs: + if not os.path.isdir(test_log_dir): + continue + for log_file in glob.glob(os.path.join(test_log_dir, '*/*')): + with open(log_file) as log: + content = log.read() + if is_hung_test(content) or not is_conformance(content): + continue + device = get_device_name(content) + if 'arm' in content: + device = 'arm' + if not device in regexp.keys(): + regexp.update({device: []}) + regexp[device].append(get_regex(content)) + for device, re_list in regexp.items(): + re_list.sort() + return regexp + + +def save_to_file(skip_folder_paths: list, regexps: dict): + for skip_folder_path in skip_folder_paths: + if not os.path.isdir(skip_folder_path): + continue + skip_files_paths = glob.glob(os.path.join(skip_folder_path, 'skip_config_*.lst')) + for skip_files_path in skip_files_paths: + for device, re_list in regexps.items(): + if device in skip_files_path: + with open(skip_files_path, 'w') as file: + file.writelines(re_list) + + +if __name__ == "__main__": + args = parse_arguments() + save_to_file(args.skip_config_folders, get_conformance_hung_test(args.input_logs)) From 1843d5cc165801d7c9c3cd44bfdf5985a9554f58 Mon Sep 17 00:00:00 2001 From: Alexander Zhogov Date: Wed, 12 May 2021 14:59:57 +0300 Subject: [PATCH 35/99] Azure CI: Remove empty MklDnnFunctionalTests (#5590) --- .ci/azure/linux.yml | 9 +-------- .ci/azure/mac.yml | 8 -------- .ci/azure/windows.yml | 11 ----------- 3 files changed, 1 insertion(+), 27 deletions(-) diff --git a/.ci/azure/linux.yml b/.ci/azure/linux.yml index 01c16af1e87..3de3240bb0f 100644 --- a/.ci/azure/linux.yml +++ b/.ci/azure/linux.yml @@ -125,6 +125,7 @@ jobs: displayName: 'nGraph UT' continueOnError: false + # python3 $(WORK_DIR)/gtest-parallel/gtest_parallel.py $(BIN_DIR)/InferenceEngineUnitTests --workers=$(WORKERS_NUMBER) --dump_json_test_results=InferenceEngineUnitTests.json --gtest_filter=*smoke* -- --gtest_print_time=1 - script: $(BIN_DIR)/InferenceEngineUnitTests --gtest_print_time=1 --gtest_output=xml:TEST-InferenceEngineUnitTests.xml displayName: 'IE UT old' continueOnError: false @@ -161,14 +162,6 @@ jobs: displayName: 'CPU FuncTests' continueOnError: false - - script: | - export DATA_PATH=$(MODELS_PATH) - export MODELS_PATH=$(MODELS_PATH) - python3 $(WORK_DIR)/gtest-parallel/gtest-parallel $(BIN_DIR)/MklDnnFunctionalTests --workers=$(WORKERS_NUMBER) --dump_json_test_results=MklDnnFunctionalTests.json --gtest_filter=*smoke* -- --gtest_print_time=1 - workingDirectory: $(WORK_DIR) - displayName: 'MklDnnFunctionalTests' - continueOnError: false - - script: | export DATA_PATH=$(MODELS_PATH) export MODELS_PATH=$(MODELS_PATH) diff --git a/.ci/azure/mac.yml b/.ci/azure/mac.yml index c3c2a631606..3ba29d392c0 100644 --- a/.ci/azure/mac.yml +++ b/.ci/azure/mac.yml @@ -137,14 +137,6 @@ jobs: displayName: 'CPU FuncTests' continueOnError: false - - script: | - export DATA_PATH=$(MODELS_PATH) - export MODELS_PATH=$(MODELS_PATH) - python3 $(WORK_DIR)/gtest-parallel/gtest-parallel $(BIN_DIR)/MklDnnFunctionalTests --workers=$(WORKERS_NUMBER) --dump_json_test_results=MklDnnFunctionalTests.json --gtest_filter=*smoke*:-smoke_MobileNet/ModelTransformationsTest.LPT/mobilenet_v2_tf_depthwise_batch1_inPluginDisabled_inTestDisabled_asymmetric* -- --gtest_print_time=1 - workingDirectory: $(WORK_DIR) - displayName: 'MklDnnFunctionalTests' - continueOnError: false - - script: | export DATA_PATH=$(MODELS_PATH) export MODELS_PATH=$(MODELS_PATH) diff --git a/.ci/azure/windows.yml b/.ci/azure/windows.yml index a8efee2deae..0ae20539c9b 100644 --- a/.ci/azure/windows.yml +++ b/.ci/azure/windows.yml @@ -167,17 +167,6 @@ jobs: displayName: 'CPU FuncTests - IB' continueOnError: false - # Add for gtest-parallel, it hangs now (CVS-33386) - #python $(WORK_DIR)\gtest-parallel\gtest-parallel $(BIN_DIR)\MklDnnFunctionalTests --workers=$(WORKERS_NUMBER) --dump_json_test_results=MklDnnFunctionalTests.json --gtest_filter=*smoke* -- --gtest_print_time=1 - - script: | - set PATH=$(TEST_ENV_PATH) - set DATA_PATH=$(MODELS_PATH) - set MODELS_PATH=$(MODELS_PATH) - rem "$(IB_TESTCONSOLE)" $(BIN_DIR)\MklDnnFunctionalTests.exe --gtest_filter=*smoke* --gtest_output=xml:TEST-MklDnnFunctionalTests-IB.xml - $(BIN_DIR)\MklDnnFunctionalTests.exe --gtest_filter=*smoke* --gtest_output=xml:TEST-MklDnnFunctionalTests.xml - displayName: 'MklDnnFunctionalTests' - continueOnError: false - - script: | set PATH=$(TEST_ENV_PATH) set DATA_PATH=$(MODELS_PATH) From 7fa93b226e2b02e098b15402367d99796b9b9708 Mon Sep 17 00:00:00 2001 From: Irina Efode Date: Wed, 12 May 2021 15:01:02 +0300 Subject: [PATCH 36/99] [IE TESTS] Skip all tests in conformance suite for myriad plugin (#5560) --- .../test_runner/skip_configs/skip_config_myriad.lst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/skip_configs/skip_config_myriad.lst b/inference-engine/tests/functional/plugin/conformance/test_runner/skip_configs/skip_config_myriad.lst index 54f642b9875..4ce2c5b20b0 100644 --- a/inference-engine/tests/functional/plugin/conformance/test_runner/skip_configs/skip_config_myriad.lst +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/skip_configs/skip_config_myriad.lst @@ -143,4 +143,7 @@ .*Add_1087636.* .*Add_2868.* .*Add_2979.* -.*Add_53543.* \ No newline at end of file +.*Add_53543.* + +# Temporary decision to skip all tests (To collect correct test number) +.* \ No newline at end of file From fe5ca28b6eb9c015776b66718e99d8945fab40c7 Mon Sep 17 00:00:00 2001 From: iliya mironov Date: Wed, 12 May 2021 15:33:03 +0300 Subject: [PATCH 37/99] Smal fix with tf env_setup (#5476) * Smal fix with tf env_setup * Fix tf loader * Fix version checker --- model-optimizer/mo/front/tf/loader.py | 2 +- model-optimizer/mo/utils/versions_checker.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/model-optimizer/mo/front/tf/loader.py b/model-optimizer/mo/front/tf/loader.py index 0e0b102b8ee..b51e14f26d5 100644 --- a/model-optimizer/mo/front/tf/loader.py +++ b/model-optimizer/mo/front/tf/loader.py @@ -215,7 +215,7 @@ def load_tf_graph_def(graph_file_name: str = "", is_binary: bool = True, checkpo if model_dir: # saved model directory try: - env_setup = get_environment_setup() + env_setup = get_environment_setup("tf") # enable eager execution temporarily while TensorFlow 2 model is being loaded tf_v1.enable_eager_execution() # code to extract GraphDef for TF 2.0 SavedModel format diff --git a/model-optimizer/mo/utils/versions_checker.py b/model-optimizer/mo/utils/versions_checker.py index 17ee21f14d1..b9495f35041 100644 --- a/model-optimizer/mo/utils/versions_checker.py +++ b/model-optimizer/mo/utils/versions_checker.py @@ -196,9 +196,10 @@ def version_check(name, installed_v, required_v, sign, not_satisfied_v): not_satisfied_v.append((name, 'installed: {}'.format(installed_v), 'required: {} {}'.format(sign, required_v))) -def get_environment_setup(): +def get_environment_setup(framework): """ Get environment setup such as Python version, TensorFlow version + :param framework: framework name :return: a dictionary of environment variables """ env_setup = dict() @@ -207,9 +208,10 @@ def get_environment_setup(): sys.version_info.micro) env_setup['python_version'] = python_version try: - exec("import tensorflow") - env_setup['tensorflow'] = sys.modules["tensorflow"].__version__ - exec("del tensorflow") + if framework == 'tf': + exec("import tensorflow") + env_setup['tensorflow'] = sys.modules["tensorflow"].__version__ + exec("del tensorflow") except (AttributeError, ImportError): pass env_setup['sys_platform'] = sys.platform @@ -228,7 +230,7 @@ def check_requirements(framework=None): :param framework: framework name :return: exit code (0 - execution successful, 1 - error) """ - env_setup = get_environment_setup() + env_setup = get_environment_setup(framework) if framework is None: framework_suffix = "" elif framework == "tf": From ed4d3fc4ed8923d06d6d7659360bf3f5696e5f12 Mon Sep 17 00:00:00 2001 From: Paul Youngsoo Ahn Date: Wed, 12 May 2021 22:00:12 +0900 Subject: [PATCH 38/99] [IE CLDNN] Disable extended eltwise fusing on gen12 (#5584) --- .../prepare_primitive_fusing.cpp | 5 +++-- .../tests/test_cases/fusings_gpu_test.cpp | 22 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/prepare_primitive_fusing.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/prepare_primitive_fusing.cpp index 21011545282..ffd8fbd245c 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/prepare_primitive_fusing.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/prepare_primitive_fusing.cpp @@ -355,6 +355,7 @@ void prepare_primitive_fusing::fuse_simple_primitives(program_impl &p) { bool recalc_processing_order = false; std::map> fusing_history; + const uint8_t supports_immad = p.get_engine().get_device_info().supports_immad; auto itr = p.get_processing_order().begin(); while (itr != p.get_processing_order().end()) { auto node_itr = itr++; @@ -520,7 +521,7 @@ void prepare_primitive_fusing::fuse_simple_primitives(program_impl &p) { // find original dependency of current_node using fusing_history // and check the number of users of it. // If the node has multiple users it's not fusible. - if (input_data.has_fused_primitives()) { + if (!supports_immad && input_data.has_fused_primitives()) { size_t num_original_dependencies = 0; auto iter = fusing_history.find(current_node_id); if (iter != fusing_history.end()) { @@ -872,7 +873,7 @@ void prepare_primitive_fusing::fuse_simple_primitives(program_impl &p) { bool merge_allowed = true; // If fused node is not convolution and fused node has multiple users, // follow the legacy checking rule - if (fused_node->is_type() && fused_node->get_users().size() > 1) { + if (!supports_immad && fused_node->is_type() && fused_node->get_users().size() > 1) { // Allowed new pattern: Elt1, Act, Elt2, Elt3, Elt4 are fused to Conv1 // * Conv1 -> Eltw1(Add) -> Act(Clamp) -> Eltw2(Mul) -> Eltw3(Mul) -> Eltw4(Add) -> Conv2 // * \–----------------------------------->/ \---------> Eltw5(Div) diff --git a/inference-engine/thirdparty/clDNN/tests/test_cases/fusings_gpu_test.cpp b/inference-engine/thirdparty/clDNN/tests/test_cases/fusings_gpu_test.cpp index a14d6d7975a..0b65758bb4d 100644 --- a/inference-engine/thirdparty/clDNN/tests/test_cases/fusings_gpu_test.cpp +++ b/inference-engine/thirdparty/clDNN/tests/test_cases/fusings_gpu_test.cpp @@ -833,9 +833,12 @@ INSTANTIATE_TEST_CASE_P(fusings_gpu, conv_fp32_prelu_eltwise, bc_test_params{CASE_CONV_FP16_4, 2, 4}, }), ); - class conv_fp32_multi_eltwise_2 : public ConvFusingTest {}; TEST_P(conv_fp32_multi_eltwise_2, basic) { + if (engine.get_info().supports_immad) { + return; + } + auto p = GetParam(); create_topologies(input_layout("input", get_input_layout(p)), data("eltwise_data", get_mem(get_output_layout(p))), @@ -866,10 +869,12 @@ INSTANTIATE_TEST_CASE_P(fusings_gpu, conv_fp32_multi_eltwise_2, class conv_fp32_multi_eltwise_2_clamp : public ConvFusingTest {}; - TEST_P(conv_fp32_multi_eltwise_2_clamp, basic) { - auto p = GetParam(); + if (engine.get_info().supports_immad) { + return; + } + auto p = GetParam(); create_topologies(input_layout("input", get_input_layout(p)), data("eltwise1_data", get_mem(get_output_layout(p))), data("bias", get_mem(get_bias_layout(p))), @@ -900,10 +905,12 @@ INSTANTIATE_TEST_CASE_P(fusings_gpu, conv_fp32_multi_eltwise_2_clamp, class conv_fp32_multi_eltwise_4_clamp : public ConvFusingTest {}; - TEST_P(conv_fp32_multi_eltwise_4_clamp, basic) { - auto p = GetParam(); + if (engine.get_info().supports_immad) { + return; + } + auto p = GetParam(); create_topologies(input_layout("input", get_input_layout(p)), data("eltwise1_data", get_mem(get_output_layout(p))), data("eltwise2_data", get_mem(get_output_layout(p))), @@ -939,6 +946,10 @@ INSTANTIATE_TEST_CASE_P(fusings_gpu, conv_fp32_multi_eltwise_4_clamp, class conv_fp32_multi_eltwise_3_fusing : public ConvFusingTest {}; TEST_P(conv_fp32_multi_eltwise_3_fusing, basic) { + if (engine.get_info().supports_immad) { + return; + } + auto p = GetParam(); create_topologies(input_layout("input", get_input_layout(p)), data("eltwise_data1", get_mem(get_output_layout(p))), @@ -988,6 +999,7 @@ TEST_P(conv_fp32_multi_eltwise_quantization, basic) { eltwise("eltwise2", "eltwise1", "quantize", eltwise_mode::prod), reorder("reorder_bfyx", "eltwise2", p.default_format, data_types::f32) ); + tolerance = 1.f; execute(p); } From b4565b7b4f3863792d1c7023e9683bec5c191072 Mon Sep 17 00:00:00 2001 From: Gleb Kazantaev Date: Wed, 12 May 2021 18:42:56 +0300 Subject: [PATCH 39/99] Add Model Optimizer --transform option (#5504) * Execute MO stages inside subprocess to have single IE check * Add --transform key * Updated ofline transformations to execute user specified passes; updated logic to raise when --transform is used * Parametrize LowLatency transformation with num_iterations key * Fixed MO and IE versions comparision * Use subprocess for offline transformations execution to catch errors * remove ie_is_available from IR; fixed typo * Fix for old IE versions * Update parse_transform key unit tests * Show available transformations * Fixed typo * Fix review comments * Fix python2 compatibility * Fixed review comments * Fixed __main__ import --- .../offline_transformations_api.pyx | 5 +- .../offline_transformations_api_impl.cpp | 3 +- .../offline_transformations_api_impl.hpp | 2 +- .../offline_transformations_api_impl_defs.pxd | 3 +- model-optimizer/automation/package_BOM.txt | 6 ++ model-optimizer/mo.py | 13 +-- model-optimizer/mo/__main__.py | 15 +-- .../mo/back/offline_transformations.py | 58 +++++++---- model-optimizer/mo/main.py | 44 +++++++-- model-optimizer/mo/main_caffe.py | 10 ++ model-optimizer/mo/main_kaldi.py | 10 ++ model-optimizer/mo/main_mxnet.py | 10 ++ model-optimizer/mo/main_onnx.py | 10 ++ model-optimizer/mo/main_tf.py | 10 ++ model-optimizer/mo/subprocess_main.py | 42 ++++++++ model-optimizer/mo/utils/check_ie_bindings.py | 26 ++--- model-optimizer/mo/utils/cli_parser.py | 98 ++++++++++++++++++- model-optimizer/mo/utils/version.py | 4 +- model-optimizer/mo_caffe.py | 13 +-- model-optimizer/mo_kaldi.py | 13 +-- model-optimizer/mo_mxnet.py | 13 +-- model-optimizer/mo_onnx.py | 13 +-- model-optimizer/mo_tf.py | 13 +-- .../unit_tests/mo/utils/cli_parser_test.py | 70 ++++++++++++- .../unit_tests/mo/utils/version_test.py | 11 ++- 25 files changed, 385 insertions(+), 130 deletions(-) create mode 100644 model-optimizer/mo/main_caffe.py create mode 100644 model-optimizer/mo/main_kaldi.py create mode 100644 model-optimizer/mo/main_mxnet.py create mode 100644 model-optimizer/mo/main_onnx.py create mode 100644 model-optimizer/mo/main_tf.py create mode 100644 model-optimizer/mo/subprocess_main.py diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api.pyx b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api.pyx index dd7300d33dd..bd101280fcb 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api.pyx +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api.pyx @@ -6,6 +6,7 @@ from ..inference_engine.ie_api cimport IENetwork from libcpp cimport bool from libcpp.string cimport string +from libc.stdint cimport int64_t def ApplyMOCTransformations(IENetwork network, bool cf): @@ -16,8 +17,8 @@ def ApplyPOTTransformations(IENetwork network, string device): C.ApplyPOTTransformations(network.impl, device) -def ApplyLowLatencyTransformation(IENetwork network): - C.ApplyLowLatencyTransformation(network.impl) +def ApplyLowLatencyTransformation(IENetwork network, int64_t num_iterations=1): + C.ApplyLowLatencyTransformation(network.impl, num_iterations) def ApplyPruningTransformation(IENetwork network): diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.cpp b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.cpp index d5c628b5b18..b9ff879da8c 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.cpp +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.cpp @@ -26,8 +26,9 @@ void InferenceEnginePython::ApplyPOTTransformations(InferenceEnginePython::IENet manager.run_passes(network.actual->getFunction()); } -void InferenceEnginePython::ApplyLowLatencyTransformation(InferenceEnginePython::IENetwork network) { +void InferenceEnginePython::ApplyLowLatencyTransformation(InferenceEnginePython::IENetwork network, int64_t num_iterations) { ngraph::pass::Manager manager; + // TODO: pass num_iterations to LowLatency manager.register_pass(); manager.register_pass(); diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.hpp b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.hpp index 81aca0622a5..504388e4afc 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.hpp +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.hpp @@ -15,7 +15,7 @@ void ApplyMOCTransformations(InferenceEnginePython::IENetwork network, bool cf); void ApplyPOTTransformations(InferenceEnginePython::IENetwork network, std::string device); -void ApplyLowLatencyTransformation(InferenceEnginePython::IENetwork network); +void ApplyLowLatencyTransformation(InferenceEnginePython::IENetwork network, int64_t num_iterations); void ApplyPruningTransformation(InferenceEnginePython::IENetwork network); diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl_defs.pxd b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl_defs.pxd index d9d50139daf..726880e9353 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl_defs.pxd +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl_defs.pxd @@ -3,6 +3,7 @@ from libcpp cimport bool from libcpp.string cimport string +from libc.stdint cimport int64_t from ..inference_engine.ie_api_impl_defs cimport IENetwork @@ -11,7 +12,7 @@ cdef extern from "offline_transformations_api_impl.hpp" namespace "InferenceEngi cdef void ApplyPOTTransformations(IENetwork network, string device) - cdef void ApplyLowLatencyTransformation(IENetwork network) + cdef void ApplyLowLatencyTransformation(IENetwork network, int64_t num_iterations) cdef void ApplyPruningTransformation(IENetwork network) diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index d236df8f3d2..b6f7236c35f 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -939,6 +939,11 @@ mo/graph/graph.py mo/graph/perm_inputs.py mo/graph/port.py mo/main.py +mo/main_caffe.py +mo/main_kaldi.py +mo/main_mxnet.py +mo/main_onnx.py +mo/main_tf.py mo/middle/__init__.py mo/middle/passes/__init__.py mo/middle/passes/conv.py @@ -1004,6 +1009,7 @@ mo/ops/unsqueeze.py mo/pipeline/__init__.py mo/pipeline/common.py mo/pipeline/unified.py +mo/subprocess_main.py mo/utils/__init__.py mo/utils/broadcasting.py mo/utils/check_ie_bindings.py diff --git a/model-optimizer/mo.py b/model-optimizer/mo.py index bc8fcf9daa9..d8a02b7f964 100755 --- a/model-optimizer/mo.py +++ b/model-optimizer/mo.py @@ -3,16 +3,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import sys - -from mo.utils.versions_checker import check_python_version # pylint: disable=no-name-in-module if __name__ == "__main__": - ret_code = check_python_version() - if ret_code: - sys.exit(ret_code) - - from mo.main import main - from mo.utils.cli_parser import get_all_cli_parser # pylint: disable=no-name-in-module - - sys.exit(main(get_all_cli_parser(), None)) + from mo.subprocess_main import subprocess_main # pylint: disable=no-name-in-module + subprocess_main(framework=None) diff --git a/model-optimizer/mo/__main__.py b/model-optimizer/mo/__main__.py index 1e84a6a65a9..9d0e0f5013e 100644 --- a/model-optimizer/mo/__main__.py +++ b/model-optimizer/mo/__main__.py @@ -1,16 +1,5 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import sys - -from mo.utils.versions_checker import check_python_version # pylint: disable=no-name-in-module - -ret_code = check_python_version() -if ret_code: - sys.exit(ret_code) - -from mo.main import main -from mo.utils.cli_parser import get_all_cli_parser # pylint: disable=no-name-in-module - -sys.exit(main(get_all_cli_parser(), None)) - +from mo.subprocess_main import subprocess_main +subprocess_main(framework=None) diff --git a/model-optimizer/mo/back/offline_transformations.py b/model-optimizer/mo/back/offline_transformations.py index 22b317ab765..e9069547484 100644 --- a/model-optimizer/mo/back/offline_transformations.py +++ b/model-optimizer/mo/back/offline_transformations.py @@ -3,28 +3,48 @@ import argparse +from mo.utils.error import Error +from mo.utils.cli_parser import parse_transform + + +def get_available_transformations(): + try: + from openvino.offline_transformations import ApplyLowLatencyTransformation # pylint: disable=import-error + return { + 'LowLatency': ApplyLowLatencyTransformation, + } + except Exception as e: + return {} + + +def apply_offline_transformations(input_model: str, framework: str, transforms: list): + # This variable is only needed by GenerateMappingFile transformation + # to produce correct mapping + extract_names = framework in ['tf', 'mxnet', 'kaldi'] + + from openvino.inference_engine import read_network # pylint: disable=import-error + from openvino.offline_transformations import ApplyMOCTransformations, GenerateMappingFile # pylint: disable=import-error + + net = read_network(input_model + "_tmp.xml", input_model + "_tmp.bin") + + available_transformations = get_available_transformations() + + for name, args in transforms: + if name not in available_transformations.keys(): + raise Error("Transformation {} is not available.".format(name)) + + available_transformations[name](net, **args) + + net.serialize(input_model + ".xml", input_model + ".bin") + path_to_mapping = input_model + ".mapping" + GenerateMappingFile(net, path_to_mapping.encode('utf-8'), extract_names) + + if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--input_model") parser.add_argument("--framework") + parser.add_argument("--transform") args = parser.parse_args() - path_to_model = args.input_model - - # This variable is only needed by GenerateMappingFile transformation - # to produce correct mapping - extract_names = True if args.framework in ['tf', 'mxnet', 'kaldi'] else False - - try: - from openvino.inference_engine import IECore, read_network # pylint: disable=import-error - from openvino.offline_transformations import ApplyMOCTransformations, GenerateMappingFile, CheckAPI # pylint: disable=import-error - except Exception as e: - print("[ WARNING ] {}".format(e)) - exit(1) - - CheckAPI() - - net = read_network(path_to_model + "_tmp.xml", path_to_model + "_tmp.bin") - net.serialize(path_to_model + ".xml", path_to_model + ".bin") - path_to_mapping = path_to_model + ".mapping" - GenerateMappingFile(net, path_to_mapping.encode('utf-8'), extract_names) + apply_offline_transformations(args.input_model, args.framework, parse_transform(args.transform)) \ No newline at end of file diff --git a/model-optimizer/mo/main.py b/model-optimizer/mo/main.py index 7783bea36c8..2a289f2d3b8 100644 --- a/model-optimizer/mo/main.py +++ b/model-optimizer/mo/main.py @@ -6,8 +6,8 @@ import datetime import logging as log import os import platform -import subprocess import sys +import subprocess import traceback from collections import OrderedDict from copy import deepcopy @@ -24,7 +24,8 @@ from mo.pipeline.unified import unified_pipeline from mo.utils import import_extensions from mo.utils.cli_parser import get_placeholder_shapes, get_tuple_values, get_model_name, \ get_common_cli_options, get_caffe_cli_options, get_tf_cli_options, get_mxnet_cli_options, get_kaldi_cli_options, \ - get_onnx_cli_options, get_mean_scale_dictionary, parse_tuple_pairs, get_freeze_placeholder_values, get_meta_info + get_onnx_cli_options, get_mean_scale_dictionary, parse_tuple_pairs, get_freeze_placeholder_values, get_meta_info, \ + parse_transform, check_available_transforms from mo.utils.error import Error, FrameworkError from mo.utils.find_ie_version import find_ie_version from mo.utils.get_ov_update_message import get_ov_update_message @@ -33,7 +34,7 @@ from mo.utils.logger import init_logger from mo.utils.model_analysis import AnalysisResults from mo.utils.utils import refer_to_faq_msg from mo.utils.version import get_version, get_simplified_mo_version, get_simplified_ie_version -from mo.utils.versions_checker import check_requirements +from mo.utils.versions_checker import check_requirements # pylint: disable=no-name-in-module def replace_ext(name: str, old: str, new: str): @@ -141,14 +142,22 @@ def prepare_ir(argv: argparse.Namespace): # This try-except is additional reinsurance that the IE # dependency search does not break the MO pipeline try: - if not find_ie_version(silent=argv.silent) and not argv.silent: + argv.ie_is_available = find_ie_version(silent=argv.silent) + + if not argv.ie_is_available and not argv.silent: print("[ WARNING ] Could not find the Inference Engine Python API. At this moment, the Inference Engine dependency is not required, but will be required in future releases.") print("[ WARNING ] Consider building the Inference Engine Python API from sources or try to install OpenVINO (TM) Toolkit using \"install_prerequisites.{}\"".format( "bat" if sys.platform == "windows" else "sh")) # If the IE was not found, it will not print the MO version, so we have to print it manually print("{}: \t{}".format("Model Optimizer version", get_version())) except Exception as e: - pass + argv.ie_is_available = False + + # This is just to check that transform key is valid and transformations are available + check_available_transforms(parse_transform(argv.transform), argv.ie_is_available) + + if argv.legacy_ir_generation and len(argv.transform) != 0: + raise Error("--legacy_ir_generation and --transform keys can not be used at the same time.") ret_code = check_requirements(framework=argv.framework) if ret_code: @@ -250,6 +259,10 @@ def emit_ir(graph: Graph, argv: argparse.Namespace): mean_data = deepcopy(graph.graph['mf']) if 'mf' in graph.graph else None input_names = deepcopy(graph.graph['input_names']) if 'input_names' in graph.graph else [] + # Remove temporary ie_is_available key from argv no to have it in IR + ie_is_available = argv.ie_is_available + del argv.ie_is_available + prepare_emit_ir(graph=graph, data_type=graph.graph['cmd_params'].data_type, output_dir=argv.output_dir, @@ -270,16 +283,16 @@ def emit_ir(graph: Graph, argv: argparse.Namespace): # This try-except is additional reinsurance that the IE # dependency search does not break the MO pipeline try: - if not argv.legacy_ir_generation and find_ie_version(silent=True): + if not argv.legacy_ir_generation and ie_is_available: path_to_offline_transformations = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'back', 'offline_transformations.py') status = subprocess.run([sys.executable, path_to_offline_transformations, "--input_model", orig_model_name, - "--framework", argv.framework], env=os.environ, timeout=10) + "--framework", argv.framework, + "--transform", argv.transform], env=os.environ) return_code = status.returncode - if return_code != 0 and not argv.silent: - log.error("offline_transformations return code {}".format(return_code), extra={'is_warning': True}) except Exception as e: + return_code = "failed" log.error(e, extra={'is_warning': True}) message = str(dict({ @@ -296,6 +309,14 @@ def emit_ir(graph: Graph, argv: argparse.Namespace): # produced by prepare_ir. This IR needs to be renamed from XXX_tmp.xml to XXX.xml suffixes = [".xml", ".bin", ".mapping"] if return_code != 0: + if len(argv.transform) != 0: + # Remove temporary IR before throwing exception + for suf in suffixes: + path_to_file = orig_model_name + "_tmp" + suf + if os.path.exists(path_to_file): + os.remove(path_to_file) + raise Error("Failed to apply transformations: {}".format(argv.transform)) + log.error("Using fallback to produce IR.", extra={'is_warning': True}) for suf in suffixes: # remove existing files @@ -400,3 +421,8 @@ def main(cli_parser: argparse.ArgumentParser, framework: str): telemetry.end_session() telemetry.force_shutdown(1.0) return 1 + + +if __name__ == "__main__": + from mo.utils.cli_parser import get_all_cli_parser + sys.exit(main(get_all_cli_parser(), None)) diff --git a/model-optimizer/mo/main_caffe.py b/model-optimizer/mo/main_caffe.py new file mode 100644 index 00000000000..bcba5c8d611 --- /dev/null +++ b/model-optimizer/mo/main_caffe.py @@ -0,0 +1,10 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import sys + +from mo.utils.cli_parser import get_caffe_cli_parser + +if __name__ == "__main__": + from mo.main import main + sys.exit(main(get_caffe_cli_parser(), 'caffe')) diff --git a/model-optimizer/mo/main_kaldi.py b/model-optimizer/mo/main_kaldi.py new file mode 100644 index 00000000000..15233333203 --- /dev/null +++ b/model-optimizer/mo/main_kaldi.py @@ -0,0 +1,10 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import sys + +from mo.utils.cli_parser import get_kaldi_cli_parser + +if __name__ == "__main__": + from mo.main import main + sys.exit(main(get_kaldi_cli_parser(), 'kaldi')) diff --git a/model-optimizer/mo/main_mxnet.py b/model-optimizer/mo/main_mxnet.py new file mode 100644 index 00000000000..91cb1953159 --- /dev/null +++ b/model-optimizer/mo/main_mxnet.py @@ -0,0 +1,10 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import sys + +from mo.utils.cli_parser import get_mxnet_cli_parser + +if __name__ == "__main__": + from mo.main import main + sys.exit(main(get_mxnet_cli_parser(), 'mxnet')) diff --git a/model-optimizer/mo/main_onnx.py b/model-optimizer/mo/main_onnx.py new file mode 100644 index 00000000000..3bf882d65e9 --- /dev/null +++ b/model-optimizer/mo/main_onnx.py @@ -0,0 +1,10 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import sys + +from mo.utils.cli_parser import get_onnx_cli_parser + +if __name__ == "__main__": + from mo.main import main + sys.exit(main(get_onnx_cli_parser(), 'onnx')) diff --git a/model-optimizer/mo/main_tf.py b/model-optimizer/mo/main_tf.py new file mode 100644 index 00000000000..3c55e4ac0e2 --- /dev/null +++ b/model-optimizer/mo/main_tf.py @@ -0,0 +1,10 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import sys + +from mo.utils.cli_parser import get_tf_cli_parser + +if __name__ == "__main__": + from mo.main import main + sys.exit(main(get_tf_cli_parser(), 'tf')) diff --git a/model-optimizer/mo/subprocess_main.py b/model-optimizer/mo/subprocess_main.py new file mode 100644 index 00000000000..64c05a96441 --- /dev/null +++ b/model-optimizer/mo/subprocess_main.py @@ -0,0 +1,42 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import os +import sys +import subprocess + +from mo.utils.versions_checker import check_python_version # pylint: disable=no-name-in-module + + +def subprocess_main(framework=None): + """ + Please keep this file compatible with python2 in order to check user python version. + + This function checks that Inference Engine Python API available and working as expected + and then in sub-process it executes main_.py files. Due to some OSs specifics we can't + just add paths to Python modules and libraries into current env. So to make Inference Engine + Python API to be available inside MO we need to use subprocess with new env. + """ + ret_code = check_python_version() + if ret_code: + sys.exit(ret_code) + + from mo.utils.find_ie_version import find_ie_version + find_ie_version(silent=True) + + mo_root_path = os.path.join(os.path.dirname(__file__), os.pardir) + + python_path_key = 'PYTHONPATH' + if python_path_key not in os.environ: + os.environ[python_path_key] = mo_root_path + else: + os.environ[python_path_key] = os.pathsep.join([os.environ[python_path_key], mo_root_path]) + + path_to_main = os.path.join(os.path.realpath(os.path.dirname(__file__)), + 'main_{}.py'.format(framework) if framework else 'main.py') + # python2 compatible code. Do not remove. + args = [sys.executable, path_to_main] + for arg in sys.argv[1:]: + args.append(arg) + status = subprocess.run(args, env=os.environ) + sys.exit(status.returncode) \ No newline at end of file diff --git a/model-optimizer/mo/utils/check_ie_bindings.py b/model-optimizer/mo/utils/check_ie_bindings.py index 6fee0828303..12c9e039e37 100644 --- a/model-optimizer/mo/utils/check_ie_bindings.py +++ b/model-optimizer/mo/utils/check_ie_bindings.py @@ -32,11 +32,20 @@ def send_telemetry(mo_version: str, message: str, event_type: str): def import_core_modules(silent: bool, path_to_module: str): - try: - from openvino.inference_engine import IECore, get_version # pylint: disable=import-error - from openvino.offline_transformations import ApplyMOCTransformations, CheckAPI # pylint: disable=import-error + """ + This function checks that InferenceEngine Python API is available + and necessary python modules exists. So the next list of imports + must contain all IE/NG Python API imports that are used inside MO. - import openvino # pylint: disable=import-error + :param silent: enables or disables logs printing to stdout + :param path_to_module: path where python API modules were found + :return: True if all imports were successful and False otherwise + """ + try: + from openvino.inference_engine import get_version, read_network # pylint: disable=import-error + from openvino.offline_transformations import ApplyMOCTransformations, ApplyLowLatencyTransformation, GenerateMappingFile # pylint: disable=import-error + + import openvino # pylint: disable=import-error if silent: return True @@ -46,15 +55,10 @@ def import_core_modules(silent: bool, path_to_module: str): print("\t- {}: \t{}".format("Inference Engine found in", os.path.dirname(openvino.__file__))) print("{}: \t{}".format("Inference Engine version", ie_version)) - print("{}: \t {}".format("Model Optimizer version", mo_version)) + print("{}: \t{}".format("Model Optimizer version", mo_version)) versions_mismatch = False - # MO and IE version have a small difference in the beginning of version because - # IE version also includes API version. For example: - # Inference Engine version: 2.1.custom_HEAD_4c8eae0ee2d403f8f5ae15b2c9ad19cfa5a9e1f9 - # Model Optimizer version: custom_HEAD_4c8eae0ee2d403f8f5ae15b2c9ad19cfa5a9e1f9 - # So to match this versions we skip IE API version. - if not re.match(r"^([0-9]+).([0-9]+).{}$".format(mo_version), ie_version): + if mo_version != ie_version: versions_mismatch = True extracted_mo_release_version = v.extract_release_version(mo_version) mo_is_custom = extracted_mo_release_version == (None, None) diff --git a/model-optimizer/mo/utils/cli_parser.py b/model-optimizer/mo/utils/cli_parser.py index b44e47fabf8..86f35ca4dfe 100644 --- a/model-optimizer/mo/utils/cli_parser.py +++ b/model-optimizer/mo/utils/cli_parser.py @@ -6,7 +6,6 @@ import ast import logging as log import os import re -import sys from collections import OrderedDict from itertools import zip_longest @@ -254,6 +253,14 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None): 'and biases are quantized to FP16.', choices=["FP16", "FP32", "half", "float"], default='float') + common_group.add_argument('--transform', + help='Apply additional transformations. ' + + 'Usage: "--transform transformation_name1[args],transformation_name2..." ' + + 'where [args] is key=value pairs separated by semicolon. ' + + 'Examples: "--transform LowLatency" or ' + + ' "--transform LowLatency[num_iterations=2]" ' + + 'Available transformations: "LowLatency"', + default="") common_group.add_argument('--disable_fusing', help='Turn off fusing of linear operations to Convolution', action=DeprecatedStoreTrue) @@ -1127,6 +1134,95 @@ def get_absolute_path(path_to_file: str) -> str: return file_path +def isfloat(value): + try: + float(value) + return True + except ValueError: + return False + + +def convert_string_to_real_type(value: str): + values = value.split(',') + for i in range(len(values)): + value = values[i] + if value.isdigit(): + values[i] = int(value) + elif isfloat(value): + values[i] = float(value) + + return values[0] if len(values) == 1 else values + + +def parse_transform(transform: str) -> list: + transforms = [] + + if len(transform) == 0: + return transforms + + all_transforms = re.findall(r"([a-zA-Z0-9]+)(\[([^\]]+)\])*(,|$)", transform) + + # Check that all characters were matched otherwise transform key value is invalid + key_len = len(transform) + for transform in all_transforms: + # In regexp we have 4 groups where 1st group - transformation_name, + # 2nd group - [args], + # 3rd group - args, <-- nested group + # 4th group - EOL + # And to check that regexp matched all string we decrease total length by the length of matched groups (1,2,4) + # In case if no arguments were given to transformation then 2nd and 3rd groups will be empty. + if len(transform) != 4: + raise Error("Unexpected transform key structure: {}".format(transform)) + key_len -= len(transform[0]) + len(transform[1]) + len(transform[3]) + + if key_len != 0: + raise Error("Unexpected transform key structure: {}".format(transform)) + + for transform in all_transforms: + name = transform[0] + args = transform[2] + + args_dict = {} + + if len(args) != 0: + for arg in args.split(';'): + m = re.match(r"^([_a-zA-Z]+)=(.+)$", arg) + if not m: + raise Error("Unrecognized attributes for transform key: {}".format(transform)) + + args_dict[m.group(1)] = convert_string_to_real_type(m.group(2)) + + transforms.append((name, args_dict)) + + return transforms + + +def check_available_transforms(transforms: list, ie_is_available: bool): + """ + This function check that transformations specified by user are available. + :param transforms: list of user specified transformations + :param ie_is_available: True if IE Python API is available and False if it is not + :return: raises an Error if IE or transformation is not available + """ + if not ie_is_available and len(transforms) != 0: + raise Error('Can not apply {} transformations due to missing Inference Engine Python API'.format( + ','.join([name for name, _ in transforms]))) + + from mo.back.offline_transformations import get_available_transformations + available_transforms = get_available_transformations() + + missing_transformations = [] + for name, _ in transforms: + if name not in available_transforms.keys(): + missing_transformations.append(name) + + if len(missing_transformations) != 0: + raise Error('Following transformations ({}) are not available. ' + 'List with available transformations ({})'.format(','.join(missing_transformations), + ','.join(available_transforms.keys()))) + return True + + def check_positive(value): try: int_value = int(value) diff --git a/model-optimizer/mo/utils/version.py b/model-optimizer/mo/utils/version.py index 6dfbdec286f..c449a2d9368 100644 --- a/model-optimizer/mo/utils/version.py +++ b/model-optimizer/mo/utils/version.py @@ -65,7 +65,9 @@ def get_simplified_ie_version(env=dict(), version=None): version = subprocess.check_output([sys.executable, os.path.join(os.path.dirname(__file__), "ie_version.py")], timeout=2, env=env).strip().decode() except: return "ie not found" + + # To support legacy IE versions m = re.match(r"^([0-9]+).([0-9]+).(.*)", version) if m and len(m.groups()) == 3: return simplify_version(m.group(3)) - return "custom" + return simplify_version(version) diff --git a/model-optimizer/mo_caffe.py b/model-optimizer/mo_caffe.py index 83cfd28b96a..1b4c7c2add2 100755 --- a/model-optimizer/mo_caffe.py +++ b/model-optimizer/mo_caffe.py @@ -3,16 +3,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import sys - -from mo.utils.versions_checker import check_python_version if __name__ == "__main__": - ret_code = check_python_version() - if ret_code: - sys.exit(ret_code) - - from mo.main import main - from mo.utils.cli_parser import get_caffe_cli_parser - - sys.exit(main(get_caffe_cli_parser(), 'caffe')) + from mo.subprocess_main import subprocess_main + subprocess_main(framework='caffe') diff --git a/model-optimizer/mo_kaldi.py b/model-optimizer/mo_kaldi.py index f6e4ca223f4..ca69fa506da 100755 --- a/model-optimizer/mo_kaldi.py +++ b/model-optimizer/mo_kaldi.py @@ -3,16 +3,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import sys - -from mo.utils.versions_checker import check_python_version if __name__ == "__main__": - ret_code = check_python_version() - if ret_code: - sys.exit(ret_code) - - from mo.main import main - from mo.utils.cli_parser import get_kaldi_cli_parser - - sys.exit(main(get_kaldi_cli_parser(), 'kaldi')) + from mo.subprocess_main import subprocess_main + subprocess_main(framework='kaldi') diff --git a/model-optimizer/mo_mxnet.py b/model-optimizer/mo_mxnet.py index 757debbcc06..a54d127b00b 100755 --- a/model-optimizer/mo_mxnet.py +++ b/model-optimizer/mo_mxnet.py @@ -3,16 +3,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import sys - -from mo.utils.versions_checker import check_python_version if __name__ == "__main__": - ret_code = check_python_version() - if ret_code: - sys.exit(ret_code) - - from mo.main import main - from mo.utils.cli_parser import get_mxnet_cli_parser - - sys.exit(main(get_mxnet_cli_parser(), 'mxnet')) + from mo.subprocess_main import subprocess_main + subprocess_main(framework='mxnet') diff --git a/model-optimizer/mo_onnx.py b/model-optimizer/mo_onnx.py index 92701d5f206..52c6a253d67 100755 --- a/model-optimizer/mo_onnx.py +++ b/model-optimizer/mo_onnx.py @@ -3,16 +3,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import sys - -from mo.utils.versions_checker import check_python_version if __name__ == "__main__": - ret_code = check_python_version() - if ret_code: - sys.exit(ret_code) - - from mo.main import main - from mo.utils.cli_parser import get_onnx_cli_parser - - sys.exit(main(get_onnx_cli_parser(), 'onnx')) + from mo.subprocess_main import subprocess_main + subprocess_main(framework='onnx') diff --git a/model-optimizer/mo_tf.py b/model-optimizer/mo_tf.py index e352958f771..a6747a12b1e 100755 --- a/model-optimizer/mo_tf.py +++ b/model-optimizer/mo_tf.py @@ -3,16 +3,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import sys - -from mo.utils.versions_checker import check_python_version if __name__ == "__main__": - ret_code = check_python_version() - if ret_code: - sys.exit(ret_code) - - from mo.main import main - from mo.utils.cli_parser import get_tf_cli_parser - - sys.exit(main(get_tf_cli_parser(), 'tf')) + from mo.subprocess_main import subprocess_main + subprocess_main(framework='tf') diff --git a/model-optimizer/unit_tests/mo/utils/cli_parser_test.py b/model-optimizer/unit_tests/mo/utils/cli_parser_test.py index a4e80a274d9..68a9994d206 100644 --- a/model-optimizer/unit_tests/mo/utils/cli_parser_test.py +++ b/model-optimizer/unit_tests/mo/utils/cli_parser_test.py @@ -14,7 +14,7 @@ import numpy.testing as npt from mo.utils.cli_parser import get_placeholder_shapes, get_tuple_values, get_mean_scale_dictionary, get_model_name, \ parse_tuple_pairs, check_positive, writable_dir, readable_dirs, \ - readable_file, get_freeze_placeholder_values + readable_file, get_freeze_placeholder_values, parse_transform, check_available_transforms from mo.utils.error import Error @@ -898,3 +898,71 @@ class PathCheckerFunctions(unittest.TestCase): def test_non_readable_file(self): with self.assertRaises(Error) as cm: readable_file(__class__.NOT_EXISTING_FILE) + + +class TransformChecker(unittest.TestCase): + def test_empty(self): + self.assertEqual(parse_transform(""), []) + + def test_single_pass(self): + self.assertEqual(parse_transform("LowLatency"), [("LowLatency", {})]) + + def test_single_pass_with_args(self): + self.assertEqual(parse_transform("LowLatency[num_iterations=2]"), + [("LowLatency", {"num_iterations": 2})]) + + def test_single_pass_with_multiple_args(self): + self.assertEqual(parse_transform("LowLatency[num_iterations=2;dummy_attr=3.14]"), + [("LowLatency", {"num_iterations": 2, "dummy_attr": 3.14})]) + + def test_multiple_passes_with_args(self): + self.assertEqual(parse_transform("LowLatency[num_iterations=2],DummyPass[type=ReLU]"), + [("LowLatency", {"num_iterations": 2}), + ("DummyPass", {"type": "ReLU"})]) + + def test_multiple_passes_with_args2(self): + self.assertEqual(parse_transform("LowLatency[num_iterations=2,3,4.15],DummyPass1,DummyPass2[types=ReLU,PReLU;values=1,2,3]"), + [("LowLatency", {"num_iterations": [2,3,4.15]}), + ("DummyPass1", {}), + ("DummyPass2", {"types": ["ReLU", "PReLU"], "values": [1,2,3]})]) + + def test_multiple_passes_no_args(self): + self.assertEqual(parse_transform("DummyPass,LowLatency2"), + [("DummyPass", {}), ("LowLatency2", {})]) + + def test_single_pass_neg(self): + self.assertRaises(Error, parse_transform, "LowLatency!") + + def test_multiple_passes_neg(self): + self.assertRaises(Error, parse_transform, "LowLatency;DummyPass") + + def test_single_pass_with_args_neg1(self): + self.assertRaises(Error, parse_transform, "LowLatency[=2]") + + def test_single_pass_with_args_neg2(self): + self.assertRaises(Error, parse_transform, "LowLatency[key=]") + + def test_single_pass_with_args_neg3(self): + self.assertRaises(Error, parse_transform, "LowLatency[]") + + def test_single_pass_with_args_neg4(self): + self.assertRaises(Error, parse_transform, "LowLatency[key=value;]") + + def test_single_pass_with_args_neg5(self): + self.assertRaises(Error, parse_transform, "LowLatency[value]") + + def test_single_pass_with_args_neg6(self): + self.assertRaises(Error, parse_transform, "LowLatency[key=value") + + @patch("mo.back.offline_transformations.get_available_transformations") + def test_check_low_latency_is_available(self, available_transformations): + available_transformations.return_value = {"LowLatency": None} + try: + check_available_transforms([("LowLatency" ,"")], True) + except Error as e: + self.assertTrue(False, "Exception \"{}\" is unexpected".format(e)) + + @patch("mo.back.offline_transformations.get_available_transformations") + def test_check_dummy_pass_is_available(self, available_transformations): + available_transformations.return_value = {"LowLatency": None} + self.assertRaises(Error, check_available_transforms, [("DummyPass", "")], True) diff --git a/model-optimizer/unit_tests/mo/utils/version_test.py b/model-optimizer/unit_tests/mo/utils/version_test.py index cf7cdeb069a..706f6ca2b67 100644 --- a/model-optimizer/unit_tests/mo/utils/version_test.py +++ b/model-optimizer/unit_tests/mo/utils/version_test.py @@ -52,11 +52,14 @@ class TestingVersion(unittest.TestCase): mock_open.return_value.__enter__ = mock_open self.assertEqual(get_simplified_mo_version(), "custom") - def test_simplify_ie_version_release(self): + def test_simplify_ie_version_release_legacy(self): self.assertEqual(get_simplified_ie_version(version="2.1.custom_releases/2021/3_4c8eae"), "2021.3") - def test_simplify_ie_version_release_neg(self): - self.assertEqual(get_simplified_ie_version(version="custom_releases/2021/3_4c8eae"), "custom") + def test_simplify_ie_version_release(self): + self.assertEqual(get_simplified_ie_version(version="custom_releases/2021/3_4c8eae"), "2021.3") + + def test_simplify_ie_version_custom_legacy(self): + self.assertEqual(get_simplified_ie_version(version="2.1.custom_my/branch/3_4c8eae"), "custom") def test_simplify_ie_version_custom(self): - self.assertEqual(get_simplified_ie_version(version="2.1.custom_my/branch/3_4c8eae"), "custom") \ No newline at end of file + self.assertEqual(get_simplified_ie_version(version="custom_my/branch/3_4c8eae"), "custom") \ No newline at end of file From f2f44ce16081579146a174f8641df2fe348a3ddd Mon Sep 17 00:00:00 2001 From: Anton Chetverikov Date: Wed, 12 May 2021 18:50:38 +0300 Subject: [PATCH 40/99] Add uint64 to data types maps (#5603) --- model-optimizer/mo/middle/passes/convert_data_type.py | 1 + model-optimizer/mo/utils/ir_engine/ir_engine.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/model-optimizer/mo/middle/passes/convert_data_type.py b/model-optimizer/mo/middle/passes/convert_data_type.py index 06fd2bb846b..85ccbe85813 100644 --- a/model-optimizer/mo/middle/passes/convert_data_type.py +++ b/model-optimizer/mo/middle/passes/convert_data_type.py @@ -42,6 +42,7 @@ SUPPORTED_DATA_TYPES = { 'int32': (np.int32, 'I32', 'i32'), 'int64': (np.int64, 'I64', 'i64'), 'bool': (np.bool, 'BOOL', 'boolean'), + 'uint64': (np.uint64, 'U64', 'u64'), # custom types 'U1': (packed_U1, 'U1', 'u1'), diff --git a/model-optimizer/mo/utils/ir_engine/ir_engine.py b/model-optimizer/mo/utils/ir_engine/ir_engine.py index 8d080d8729a..b124e6d3004 100644 --- a/model-optimizer/mo/utils/ir_engine/ir_engine.py +++ b/model-optimizer/mo/utils/ir_engine/ir_engine.py @@ -301,6 +301,7 @@ class IREngine(object): 'I4': (1, np.uint8), 'BOOL': (1, np.bool), 'BIN': (1, np.uint8), + 'U64': (8, np.uint64) } type_size, dtype = precision_map[precision] layer_attrs[tag] = (int(offset), int(size) // type_size, in_port, dtype) @@ -316,7 +317,7 @@ class IREngine(object): """ normalized_attrs = {} for attr, value in attrs.items(): - value = value.replace('\"', '') + value = value.replace('\"', '').replace(' ', '') value = value.split(',') n_value = [] for val in value: From 4d7eeede3578ca048b3574e40f798db24278921b Mon Sep 17 00:00:00 2001 From: Mikhail Nosov Date: Wed, 12 May 2021 21:43:35 +0300 Subject: [PATCH 41/99] Add LoadNetwork(modelPath) to plugin interface (#5606) --- inference-engine/src/gna_plugin/gna_plugin.hpp | 2 ++ inference-engine/src/inference_engine/ie_core.cpp | 5 +++-- .../src/inference_engine/ie_plugin_cpp.hpp | 4 ++++ .../cpp_interfaces/impl/ie_plugin_internal.hpp | 6 ++++++ .../interface/ie_iplugin_internal.hpp | 10 ++++++++++ inference-engine/src/plugin_api/ie_icore.hpp | 15 +++++++++++++++ .../mocks/cpp_interfaces/interface/mock_icore.hpp | 2 ++ .../interface/mock_iinference_plugin.hpp | 2 ++ .../ie_infer_async_request_base_test.cpp | 8 ++++---- .../ie_memory_state_internal_test.cpp | 4 ++-- .../ie_executable_network_test.cpp | 5 +++-- 11 files changed, 53 insertions(+), 10 deletions(-) diff --git a/inference-engine/src/gna_plugin/gna_plugin.hpp b/inference-engine/src/gna_plugin/gna_plugin.hpp index 3e54c224746..33df51710ba 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.hpp +++ b/inference-engine/src/gna_plugin/gna_plugin.hpp @@ -110,6 +110,8 @@ class GNAPlugin : public InferenceEngine::IInferencePlugin { InferenceEngine::IExecutableNetworkInternal::Ptr LoadNetwork(const InferenceEngine::CNNNetwork &network, const std::map &config_map, InferenceEngine::RemoteContext::Ptr context) override { THROW_GNA_EXCEPTION << "Not implemented"; } + InferenceEngine::ExecutableNetwork LoadNetwork(const std::string &modelPath, + const std::map &config_map) override { THROW_GNA_EXCEPTION << "Not implemented"; } bool Infer(const InferenceEngine::Blob &input, InferenceEngine::Blob &result); void SetCore(InferenceEngine::ICore*) noexcept override {} InferenceEngine::ICore* GetCore() const noexcept override {return nullptr;} diff --git a/inference-engine/src/inference_engine/ie_core.cpp b/inference-engine/src/inference_engine/ie_core.cpp index 1bc038ff071..14cd4d9a40e 100644 --- a/inference-engine/src/inference_engine/ie_core.cpp +++ b/inference-engine/src/inference_engine/ie_core.cpp @@ -493,9 +493,8 @@ public: return res; } - // TODO: In future this method can be added to ICore interface ExecutableNetwork LoadNetwork(const std::string& modelPath, const std::string& deviceName, - const std::map& config) { + const std::map& config) override { OV_ITT_SCOPE(FIRST_INFERENCE, itt::domains::IE_LT, "Core::LoadNetwork::Path"); auto parsed = parseDeviceNameIntoConfig(deviceName, config); auto plugin = GetCPPPluginByName(parsed._deviceName); @@ -511,6 +510,8 @@ public: auto cnnNetwork = ReadNetwork(modelPath, std::string()); res = LoadNetworkImpl(cnnNetwork, plugin, parsed._config, nullptr, hash, modelPath); } + } else if (cacheManager) { + res = plugin.LoadNetwork(modelPath, parsed._config); } else { auto cnnNetwork = ReadNetwork(modelPath, std::string()); res = LoadNetworkImpl(cnnNetwork, plugin, parsed._config, nullptr, {}, modelPath); diff --git a/inference-engine/src/inference_engine/ie_plugin_cpp.hpp b/inference-engine/src/inference_engine/ie_plugin_cpp.hpp index d87b16765d6..d40bdc478aa 100644 --- a/inference-engine/src/inference_engine/ie_plugin_cpp.hpp +++ b/inference-engine/src/inference_engine/ie_plugin_cpp.hpp @@ -88,6 +88,10 @@ public: PLUGIN_CALL_STATEMENT(return ExecutableNetwork(actual->LoadNetwork(network, config, context), actual)); } + ExecutableNetwork LoadNetwork(const std::string& modelPath, const std::map& config) { + PLUGIN_CALL_STATEMENT(return actual->LoadNetwork(modelPath, config)); + } + QueryNetworkResult QueryNetwork(const CNNNetwork& network, const std::map& config) const { QueryNetworkResult res; diff --git a/inference-engine/src/plugin_api/cpp_interfaces/impl/ie_plugin_internal.hpp b/inference-engine/src/plugin_api/cpp_interfaces/impl/ie_plugin_internal.hpp index 2621c73a340..dcaf4a1e529 100644 --- a/inference-engine/src/plugin_api/cpp_interfaces/impl/ie_plugin_internal.hpp +++ b/inference-engine/src/plugin_api/cpp_interfaces/impl/ie_plugin_internal.hpp @@ -72,6 +72,12 @@ public: return impl; } + ExecutableNetwork LoadNetwork(const std::string& modelPath, + const std::map& config) override { + auto cnnNet = GetCore()->ReadNetwork(modelPath, std::string()); + return GetCore()->LoadNetwork(cnnNet, GetName(), config); + } + IExecutableNetworkInternal::Ptr ImportNetwork(const std::string& modelFileName, const std::map& config) override { (void)modelFileName; diff --git a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp index 894605d3d79..18f4658d6a4 100644 --- a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp +++ b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp @@ -166,6 +166,16 @@ public: virtual std::shared_ptr LoadNetwork(const CNNNetwork& network, const std::map& config, RemoteContext::Ptr context) = 0; + + /** + * @brief Creates an executable network from model file path + * @param modelPath A path to model + * @param config A string-string map of config parameters relevant only for this load operation + * @return Created Executable Network object + */ + virtual ExecutableNetwork LoadNetwork(const std::string& modelPath, + const std::map& config) = 0; + /** * @brief Registers extension within plugin * @param extension - pointer to already loaded extension diff --git a/inference-engine/src/plugin_api/ie_icore.hpp b/inference-engine/src/plugin_api/ie_icore.hpp index d8acf837640..6c35277726f 100644 --- a/inference-engine/src/plugin_api/ie_icore.hpp +++ b/inference-engine/src/plugin_api/ie_icore.hpp @@ -66,6 +66,21 @@ public: virtual ExecutableNetwork LoadNetwork(const CNNNetwork& network, const std::string& deviceName, const std::map& config = {}) = 0; + /** + * @brief Creates an executable network from a model file. + * + * Users can create as many networks as they need and use + * them simultaneously (up to the limitation of the hardware resources) + * + * @param modelPath Path to model + * @param deviceName Name of device to load network to + * @param config Optional map of pairs: (config parameter name, config parameter value) relevant only for this load + * operation + * @return An executable network reference + */ + virtual ExecutableNetwork LoadNetwork(const std::string& modelPath, const std::string& deviceName, + const std::map& config) = 0; + /** * @brief Creates an executable network from a previously exported network * @param networkModel network model stream diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp index c1adf355f16..7e264217bf9 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp @@ -18,6 +18,8 @@ public: const InferenceEngine::CNNNetwork&, const std::string&, const std::map&)); MOCK_METHOD3(LoadNetwork, InferenceEngine::ExecutableNetwork( const InferenceEngine::CNNNetwork&, const InferenceEngine::RemoteContext::Ptr &, const std::map&)); + MOCK_METHOD3(LoadNetwork, InferenceEngine::ExecutableNetwork( + const std::string &, const std::string &, const std::map&)); MOCK_METHOD3(ImportNetwork, InferenceEngine::ExecutableNetwork( std::istream&, const std::string&, const std::map&)); diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp index a36e1edcf93..7f450f660f3 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp @@ -15,6 +15,8 @@ public: MOCK_METHOD1(AddExtension, void(InferenceEngine::IExtensionPtr)); MOCK_METHOD2(LoadNetwork, std::shared_ptr( const InferenceEngine::CNNNetwork&, const std::map&)); + MOCK_METHOD2(LoadNetwork, InferenceEngine::ExecutableNetwork( + const std::string&, const std::map&)); MOCK_METHOD2(ImportNetwork, std::shared_ptr( const std::string&, const std::map&)); MOCK_METHOD1(SetConfig, void(const std::map &)); diff --git a/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_infer_async_request_base_test.cpp b/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_infer_async_request_base_test.cpp index a848d66fda6..73ecba07d82 100644 --- a/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_infer_async_request_base_test.cpp +++ b/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_infer_async_request_base_test.cpp @@ -199,9 +199,9 @@ protected: mockIExeNet = std::make_shared(); ON_CALL(*mockIExeNet, CreateInferRequest()).WillByDefault(Return(mock_request)); std::unique_ptr mockIPluginPtr{new MockIInferencePlugin}; - ON_CALL(*mockIPluginPtr, LoadNetwork(_, _)).WillByDefault(Return(mockIExeNet)); + ON_CALL(*mockIPluginPtr, LoadNetwork(MatcherCast(_), _)).WillByDefault(Return(mockIExeNet)); plugin = InferenceEngine::InferencePlugin{InferenceEngine::details::SOPointer{mockIPluginPtr.release()}}; - exeNetwork = plugin.LoadNetwork({}, {}); + exeNetwork = plugin.LoadNetwork(CNNNetwork{}, {}); request = exeNetwork.CreateInferRequest(); _incorrectName = "incorrect_name"; _inputName = MockNotEmptyICNNNetwork::INPUT_BLOB_NAME; @@ -223,9 +223,9 @@ protected: auto mockIExeNet = std::make_shared(); ON_CALL(*mockIExeNet, CreateInferRequest()).WillByDefault(Return(mockInferRequestInternal)); std::unique_ptr mockIPluginPtr{new MockIInferencePlugin}; - ON_CALL(*mockIPluginPtr, LoadNetwork(_, _)).WillByDefault(Return(mockIExeNet)); + ON_CALL(*mockIPluginPtr, LoadNetwork(MatcherCast(_), _)).WillByDefault(Return(mockIExeNet)); auto plugin = InferenceEngine::InferencePlugin{InferenceEngine::details::SOPointer{mockIPluginPtr.release()}}; - auto exeNetwork = plugin.LoadNetwork({}, {}); + auto exeNetwork = plugin.LoadNetwork(CNNNetwork{}, {}); return exeNetwork.CreateInferRequest(); } diff --git a/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp b/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp index c37408606d2..0557ed203b1 100644 --- a/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp +++ b/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp @@ -36,9 +36,9 @@ class VariableStateTests : public ::testing::Test { mockVariableStateInternal = make_shared(); ON_CALL(*mockExeNetworkInternal, CreateInferRequest()).WillByDefault(Return(mockInferRequestInternal)); std::unique_ptr mockIPluginPtr{new MockIInferencePlugin}; - ON_CALL(*mockIPluginPtr, LoadNetwork(_, _)).WillByDefault(Return(mockExeNetworkInternal)); + ON_CALL(*mockIPluginPtr, LoadNetwork(MatcherCast(_), _)).WillByDefault(Return(mockExeNetworkInternal)); plugin = InferenceEngine::InferencePlugin{InferenceEngine::details::SOPointer{mockIPluginPtr.release()}}; - net = plugin.LoadNetwork({}, {}); + net = plugin.LoadNetwork(CNNNetwork{}, {}); req = net.CreateInferRequest(); } }; diff --git a/inference-engine/tests/unit/inference_engine/ie_executable_network_test.cpp b/inference-engine/tests/unit/inference_engine/ie_executable_network_test.cpp index e205be6cd92..1df88845775 100644 --- a/inference-engine/tests/unit/inference_engine/ie_executable_network_test.cpp +++ b/inference-engine/tests/unit/inference_engine/ie_executable_network_test.cpp @@ -20,6 +20,7 @@ #include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp" using testing::_; +using testing::MatcherCast; using testing::Throw; using testing::Ref; using testing::Return; @@ -52,9 +53,9 @@ protected: virtual void SetUp() { mockIExeNet = std::make_shared(); std::unique_ptr mockIPluginPtr{new MockIInferencePlugin}; - ON_CALL(*mockIPluginPtr, LoadNetwork(_, _)).WillByDefault(Return(mockIExeNet)); + ON_CALL(*mockIPluginPtr, LoadNetwork(MatcherCast(_), _)).WillByDefault(Return(mockIExeNet)); plugin = InferenceEngine::InferencePlugin{InferenceEngine::details::SOPointer{mockIPluginPtr.release()}}; - exeNetwork = plugin.LoadNetwork({}, {}); + exeNetwork = plugin.LoadNetwork(CNNNetwork{}, {}); } }; From 0383b44776cba46383dd804286977854fd3bfd46 Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Wed, 12 May 2021 22:49:40 +0300 Subject: [PATCH 42/99] added RNN-t conversion doc (#5139) * added RNN-t conversion doc * applied review comments * a couple of corrections * added pip3 everywhere * fixed a typo * applied review comments * title name fix * applied Tatiana's comments round 2 * fixed a typo for 'inference' * fixed typo in MLCommons name * moved to PyTorch* specific, applied comments * pytorch_specific typo * froze MLCommons revision to r1.0; fixed typo in MLCommons relative path --- .../pytorch_specific/Convert_RNNT.md | 107 ++++++++++++++++++ docs/doxygen/ie_docs.xml | 1 + 2 files changed, 108 insertions(+) create mode 100644 docs/MO_DG/prepare_model/convert_model/pytorch_specific/Convert_RNNT.md diff --git a/docs/MO_DG/prepare_model/convert_model/pytorch_specific/Convert_RNNT.md b/docs/MO_DG/prepare_model/convert_model/pytorch_specific/Convert_RNNT.md new file mode 100644 index 00000000000..a58e886d4f4 --- /dev/null +++ b/docs/MO_DG/prepare_model/convert_model/pytorch_specific/Convert_RNNT.md @@ -0,0 +1,107 @@ +# Convert PyTorch\* RNN-T Model to the Intermediate Representation (IR) {#openvino_docs_MO_DG_prepare_model_convert_model_pytorch_specific_Convert_RNNT} + +This instruction covers conversion of RNN-T model from [MLCommons](https://github.com/mlcommons) repository. Follow +the steps below to export a PyTorch* model into ONNX* before converting it to IR: + +**Step 1**. Clone RNN-T PyTorch implementation from MLCommons repository (revision r1.0). Make a shallow clone to pull +only RNN-T model without full repository. If you already have a full repository, skip this and go to **Step 2**: +```bash +git clone -b r1.0 -n https://github.com/mlcommons/inference rnnt_for_openvino --depth 1 +cd rnnt_for_openvino +git checkout HEAD speech_recognition/rnnt +``` + +**Step 2**. If you already have a full clone of MLCommons inference repository, create a folder for +pretrained PyTorch model, where conversion into IR will take place. You will also need to specify the path to +your full clone at **Step 5**. Skip this step if you have a shallow clone. + +```bash +mkdir rnnt_for_openvino +cd rnnt_for_openvino +``` + +**Step 3**. Download pretrained weights for PyTorch implementation from https://zenodo.org/record/3662521#.YG21DugzZaQ. +For UNIX*-like systems you can use wget: +```bash +wget https://zenodo.org/record/3662521/files/DistributedDataParallel_1576581068.9962234-epoch-100.pt +``` +The link was taken from `setup.sh` in the `speech_recoginitin/rnnt` subfolder. You will get exactly the same weights as +if you were following the steps from https://github.com/mlcommons/inference/tree/master/speech_recognition/rnnt. + +**Step 4**. Install required python* packages: +```bash +pip3 install torch toml +``` + +**Step 5**. Export RNN-T model into ONNX with the script below. Copy the code below into a file named +`export_rnnt_to_onnx.py` and run it in the current directory `rnnt_for_openvino`: + +> **NOTE**: If you already have a full clone of MLCommons inference repository, you need to +> specify `mlcommons_inference_path` variable. + +```python +import toml +import torch +import sys + + +def load_and_migrate_checkpoint(ckpt_path): + checkpoint = torch.load(ckpt_path, map_location="cpu") + migrated_state_dict = {} + for key, value in checkpoint['state_dict'].items(): + key = key.replace("joint_net", "joint.net") + migrated_state_dict[key] = value + del migrated_state_dict["audio_preprocessor.featurizer.fb"] + del migrated_state_dict["audio_preprocessor.featurizer.window"] + return migrated_state_dict + + +mlcommons_inference_path = './' # specify relative path for MLCommons inferene +checkpoint_path = 'DistributedDataParallel_1576581068.9962234-epoch-100.pt' +config_toml = 'speech_recognition/rnnt/pytorch/configs/rnnt.toml' +config = toml.load(config_toml) +rnnt_vocab = config['labels']['labels'] +sys.path.insert(0, mlcommons_inference_path + 'speech_recognition/rnnt/pytorch') + +from model_separable_rnnt import RNNT + +model = RNNT(config['rnnt'], len(rnnt_vocab) + 1, feature_config=config['input_eval']) +model.load_state_dict(load_and_migrate_checkpoint(checkpoint_path)) + +seq_length, batch_size, feature_length = 157, 1, 240 +inp = torch.randn([seq_length, batch_size, feature_length]) +feature_length = torch.LongTensor([seq_length]) +x_padded, x_lens = model.encoder(inp, feature_length) +torch.onnx.export(model.encoder, (inp, feature_length), "rnnt_encoder.onnx", opset_version=12, + input_names=['input.1', '1'], dynamic_axes={'input.1': {0: 'seq_len', 1: 'batch'}}) + +symbol = torch.LongTensor([[20]]) +hidden = torch.randn([2, batch_size, 320]), torch.randn([2, batch_size, 320]) +g, hidden = model.prediction.forward(symbol, hidden) +torch.onnx.export(model.prediction, (symbol, hidden), "rnnt_prediction.onnx", opset_version=12, + input_names=['input.1', '1', '2'], + dynamic_axes={'input.1': {0: 'batch'}, '1': {1: 'batch'}, '2': {1: 'batch'}}) + +f = torch.randn([batch_size, 1, 1024]) +model.joint.forward(f, g) +torch.onnx.export(model.joint, (f, g), "rnnt_joint.onnx", opset_version=12, + input_names=['0', '1'], dynamic_axes={'0': {0: 'batch'}, '1': {0: 'batch'}}) +``` + +```bash +python3 export_rnnt_to_onnx.py +``` + +After completing this step, the files rnnt_encoder.onnx, rnnt_prediction.onnx, and rnnt_joint.onnx will be saved in +the current directory. + +**Step 6**. Run the conversion command: + +```bash +python3 {path_to_openvino}/mo.py --input_model rnnt_encoder.onnx --input "input.1[157 1 240],1->157" +python3 {path_to_openvino}/mo.py --input_model rnnt_prediction.onnx --input "input.1[1 1],1[2 1 320],2[2 1 320]" +python3 {path_to_openvino}/mo.py --input_model rnnt_joint.onnx --input "0[1 1 1024],1[1 1 320]" +``` +Please note that hardcoded value for sequence length = 157 was taken from the MLCommons, but conversion to IR preserves +network [reshapeability](../../../../IE_DG/ShapeInference.md); this means you can change input shapes manually to any value either during conversion or +inference. diff --git a/docs/doxygen/ie_docs.xml b/docs/doxygen/ie_docs.xml index 688e80d0215..76fe06457d6 100644 --- a/docs/doxygen/ie_docs.xml +++ b/docs/doxygen/ie_docs.xml @@ -56,6 +56,7 @@ limitations under the License. + From f928f7fc56afce6ec7b6889aaf13ab8d3b21e8d0 Mon Sep 17 00:00:00 2001 From: Katarzyna Mitrus Date: Thu, 13 May 2021 06:44:57 +0200 Subject: [PATCH 43/99] DeformablePSROIPoolig reference implementation (#5116) * Reference implementation init * Backend tests * Single layer tests * Update offset range in layer tests * Align int types with ng op * Update spatial bins type * Type update * Fix sub bin calculation in mkldnn plugin * Update summarize py file * Align result type * Refactoring * Apply review comments * Add serialize layar tests * Adjust int comparison * Adjust code style * Use clamp reference * Unify style * Additional check for negative output dim * Set tensor output shape in evaluate * Add visit attributes test * Small refactor * Code style (namespace comments) * Fix CommonTestsUtils::fill_data_roi usage. This function was generalized in PR #5432 and its siganutre has changed. * Update licenese header with mention about original authors. * Replace MIT SPDX full license name with short identifier. * Fix sub bin calculation in mkldnn plugin Co-authored-by: jdanieck --- .../nodes/mkldnn_psroi_pooling_node.cpp | 4 +- .../single_layer/deformable_psroi_pooling.cpp | 35 + .../deformable_psroi_pooling.cpp | 52 ++ .../deformable_psroi_pooling.hpp | 15 + .../single_layer/deformable_psroi_pooling.hpp | 48 ++ .../single_layer/deformable_psroi_pooling.cpp | 131 ++++ .../layer_tests_summary/utils/constants.py | 1 + .../reference/deformable_psroi_pooling.hpp | 231 ++++++ .../core/src/op/deformable_psroi_pooling.cpp | 3 + ngraph/test/CMakeLists.txt | 2 + .../backend/deformable_psroi_pooling.in.cpp | 689 ++++++++++++++++++ .../runtime/interpreter/evaluates_map.cpp | 51 ++ .../runtime/interpreter/opset_int_tbl.hpp | 1 + .../type_prop/deformable_psroi_pooling.cpp | 27 + .../visitors/op/deformable_psroi_pooling.cpp | 46 ++ 15 files changed, 1334 insertions(+), 2 deletions(-) create mode 100644 inference-engine/tests/functional/inference_engine/serialization/single_layer/deformable_psroi_pooling.cpp create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/deformable_psroi_pooling.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/single_layer_tests/deformable_psroi_pooling.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/deformable_psroi_pooling.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/src/single_layer/deformable_psroi_pooling.cpp create mode 100644 ngraph/core/reference/include/ngraph/runtime/reference/deformable_psroi_pooling.hpp create mode 100644 ngraph/test/backend/deformable_psroi_pooling.in.cpp create mode 100644 ngraph/test/visitors/op/deformable_psroi_pooling.cpp diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_psroi_pooling_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_psroi_pooling_node.cpp index 521dd248bdd..393ef27921a 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_psroi_pooling_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_psroi_pooling_node.cpp @@ -429,8 +429,8 @@ void MKLDNNPSROIPoolingNode::executeBilinearDeformable(const inputType *srcData, float binSizeH = roiHeight / static_cast(pooledHeight); float binSizeW = roiWidth / static_cast(pooledWidth); - float subBinSizeH = binSizeH / static_cast(spatialBinsX); - float subBinSizeW = binSizeW / static_cast(spatialBinsY); + float subBinSizeH = binSizeH / static_cast(spatialBinsY); + float subBinSizeW = binSizeW / static_cast(spatialBinsX); int partH = h * partSize / pooledHeight; int partW = w * partSize / pooledWidth; diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/deformable_psroi_pooling.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/deformable_psroi_pooling.cpp new file mode 100644 index 00000000000..ffdedd39905 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/deformable_psroi_pooling.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "shared_test_classes/single_layer/deformable_psroi_pooling.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + TEST_P(DeformablePSROIPoolingLayerTest, Serialize) { + Serialize(); + } + + const auto deformablePSROIParams = ::testing::Combine( + ::testing::ValuesIn(std::vector>{{3, 8, 16, 16}, {1, 8, 67, 32}}), // data input shape + ::testing::Values(std::vector{10, 5}), // rois input shape + // Empty offsets shape means test without optional third input + ::testing::ValuesIn(std::vector>{{}, {10, 2, 2, 2}}), // offsets input shape + ::testing::Values(2), // output_dim + ::testing::Values(2), // group_size + ::testing::ValuesIn(std::vector{1.0, 0.5, 0.0625}), // spatial scale + ::testing::ValuesIn(std::vector>{{1, 1}, {2, 2}, {3, 3}, {2, 3}}), // spatial_bins_x_y + ::testing::ValuesIn(std::vector{0.0, 0.01, 0.5}), // trans_std + ::testing::Values(2)); // part_size + + const auto deformablePSROICases_test_params = ::testing::Combine( + deformablePSROIParams, + ::testing::Values(InferenceEngine::Precision::FP32), // Net precision + ::testing::Values(CommonTestUtils::DEVICE_CPU)); // Device name + + INSTANTIATE_TEST_CASE_P(smoke_TestsDeformablePSROIPooling, DeformablePSROIPoolingLayerTest, deformablePSROICases_test_params, + DeformablePSROIPoolingLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/deformable_psroi_pooling.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/deformable_psroi_pooling.cpp new file mode 100644 index 00000000000..4a0a16c3822 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/deformable_psroi_pooling.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "single_layer_tests/deformable_psroi_pooling.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + const auto deformablePSROIParams = ::testing::Combine( + ::testing::ValuesIn(std::vector>{{3, 8, 16, 16}, {1, 8, 67, 32}}), // data input shape + ::testing::Values(std::vector{10, 5}), // rois input shape + // Empty offsets shape means test without optional third input + ::testing::ValuesIn(std::vector>{{}, {10, 2, 2, 2}}), // offsets input shape + ::testing::Values(2), // output_dim + ::testing::Values(2), // group_size + ::testing::ValuesIn(std::vector{1.0, 0.5, 0.0625}), // spatial scale + ::testing::ValuesIn(std::vector>{{1, 1}, {2, 2}, {3, 3}, {2, 3}}), // spatial_bins_x_y + ::testing::ValuesIn(std::vector{0.0, 0.01, 0.5}), // trans_std + ::testing::Values(2)); + + const auto deformablePSROICases_test_params = ::testing::Combine( + deformablePSROIParams, + ::testing::Values(InferenceEngine::Precision::FP32), // Net precision + ::testing::Values(CommonTestUtils::DEVICE_CPU)); // Device name + + INSTANTIATE_TEST_CASE_P(smoke_TestsDeformablePSROIPooling, DeformablePSROIPoolingLayerTest, deformablePSROICases_test_params, + DeformablePSROIPoolingLayerTest::getTestCaseName); + + + const auto deformablePSROIParams_advanced = ::testing::Combine( + ::testing::ValuesIn(std::vector>{{2, 441, 63, 38}}), // data input shape + ::testing::Values(std::vector{30, 5}), // rois input shape + ::testing::Values(std::vector{30, 2, 3, 3}), // offsets input shape + ::testing::Values(49), // output_dim + ::testing::Values(3), // group_size + ::testing::ValuesIn(std::vector{0.0625}), // spatial scale + ::testing::ValuesIn(std::vector>{{4, 4}}), // spatial_bins_x_y + ::testing::ValuesIn(std::vector{0.1}), // trans_std + ::testing::Values(3)); // part_size + + const auto deformablePSROICases_test_params_advanced = ::testing::Combine( + deformablePSROIParams_advanced, + ::testing::Values(InferenceEngine::Precision::FP32), // Net precision + ::testing::Values(CommonTestUtils::DEVICE_CPU)); // Device name + + INSTANTIATE_TEST_CASE_P(smoke_TestsDeformablePSROIPooling_advanced, DeformablePSROIPoolingLayerTest, deformablePSROICases_test_params_advanced, + DeformablePSROIPoolingLayerTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/deformable_psroi_pooling.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/deformable_psroi_pooling.hpp new file mode 100644 index 00000000000..34773332376 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/deformable_psroi_pooling.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "shared_test_classes/single_layer/deformable_psroi_pooling.hpp" + +namespace LayerTestsDefinitions { + +TEST_P(DeformablePSROIPoolingLayerTest, CompareWithRefs) { + Run(); +} + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/deformable_psroi_pooling.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/deformable_psroi_pooling.hpp new file mode 100644 index 00000000000..f870e11aba8 --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/deformable_psroi_pooling.hpp @@ -0,0 +1,48 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +#include "ngraph_functions/builders.hpp" +#include "ngraph_functions/utils/ngraph_helpers.hpp" + +#include "shared_test_classes/base/layer_test_utils.hpp" + +namespace LayerTestsDefinitions { + +using deformablePSROISpecificParams = std::tuple< + std::vector, // data input shape + std::vector, // rois input shape + std::vector, // trans input shape + int64_t, // output_dim + int64_t, // group_size + float, // spatial_scale + std::vector, // spatial_bins_x_y + float, // trans_std + int64_t>; // part_size + +using deformablePSROILayerTestParams = std::tuple< + deformablePSROISpecificParams, + InferenceEngine::Precision, // Net precision + LayerTestsUtils::TargetDevice>; // Device name + +class DeformablePSROIPoolingLayerTest : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { + public: + static std::string getTestCaseName(testing::TestParamInfo obj); + void GenerateInputs() override; + + protected: + void SetUp() override; + + private: + float spatialScale_; + }; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/deformable_psroi_pooling.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/deformable_psroi_pooling.cpp new file mode 100644 index 00000000000..4f8fa43b06a --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/deformable_psroi_pooling.cpp @@ -0,0 +1,131 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/single_layer/deformable_psroi_pooling.hpp" + + +namespace LayerTestsDefinitions { + + std::string DeformablePSROIPoolingLayerTest::getTestCaseName(testing::TestParamInfo obj) { + std::vector dataShape; + std::vector roisShape; + std::vector offsetsShape; + int64_t outputDim; + int64_t groupSize; + float spatialScale; + std::vector spatialBinsXY; + float trans_std; + int64_t part_size; + InferenceEngine::Precision netPrecision; + std::string targetDevice; + deformablePSROISpecificParams opParams; + + std::tie(opParams, netPrecision, targetDevice) = obj.param; + std::tie(dataShape, roisShape, offsetsShape, outputDim, groupSize, spatialScale, spatialBinsXY, + trans_std, part_size) = opParams; + + std::ostringstream result; + + result << "data_shape=" << CommonTestUtils::vec2str(dataShape) << "_"; + result << "rois_shape=" << CommonTestUtils::vec2str(roisShape) << "_"; + result << "offsets_shape=" << CommonTestUtils::vec2str(offsetsShape) << "_"; + result << "out_dim=" << outputDim << "_"; + result << "group_size=" << groupSize << "_"; + result << "scale=" << spatialScale << "_"; + result << "bins_x=" << spatialBinsXY[0] << "_"; + result << "bins_y=" << spatialBinsXY[1] << "_"; + result << "trans_std=" << trans_std << "_"; + result << "part_size=" << part_size << "_"; + result << "prec=" << netPrecision.name() << "_"; + result << "dev=" << targetDevice; + return result.str(); + } + + void DeformablePSROIPoolingLayerTest::GenerateInputs() { + auto data_input_shape = cnnNetwork.getInputShapes().begin()->second; + const auto batch_distrib = data_input_shape[0] - 1; + const auto height = data_input_shape[2] / spatialScale_; + const auto width = data_input_shape[3] / spatialScale_; + + size_t it = 0; + for (const auto &input : cnnNetwork.getInputsInfo()) { + const auto &info = input.second; + InferenceEngine::Blob::Ptr blob; + + if (it == 0) { + blob = GenerateInput(*info); + } else if (it == 1) { + blob = make_blob_with_precision(info->getTensorDesc()); + blob->allocate(); + CommonTestUtils::fill_data_roi(blob, batch_distrib, + height, width, 1.0f, true); + } else { + blob = make_blob_with_precision(info->getTensorDesc()); + blob->allocate(); + std::vector offset_data = CommonTestUtils::generate_float_numbers(blob->size(), -0.9, 0.9); + CommonTestUtils::fill_data_float_array(blob, &offset_data[0], blob->size()); + } + inputs.push_back(blob); + it++; + } + } + + void DeformablePSROIPoolingLayerTest::SetUp() { + std::vector dataShape; + std::vector roisShape; + std::vector offsetsShape; + int64_t outputDim; + int64_t groupSize; + std::string mode = "bilinear_deformable"; + std::vector spatialBinsXY; + float trans_std; + int64_t part_size; + InferenceEngine::Precision netPrecision; + deformablePSROISpecificParams opParams; + + std::tie(opParams, netPrecision, targetDevice) = this->GetParam(); + std::tie(dataShape, roisShape, offsetsShape, outputDim, groupSize, spatialScale_, spatialBinsXY, + trans_std, part_size) = opParams; + + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + ngraph::ParameterVector params; + ngraph::OutputVector inputs; + std::shared_ptr defomablePSROIPooling; + + if (offsetsShape.empty()) { // Test without optional third input (offsets) + params = ngraph::builder::makeParams(ngPrc, {dataShape, roisShape}); + inputs = ngraph::helpers::convert2OutputVector( + ngraph::helpers::castOps2Nodes(params)); + defomablePSROIPooling = std::make_shared(inputs[0], + inputs[1], + outputDim, + spatialScale_, + groupSize, + mode, + spatialBinsXY[0], + spatialBinsXY[1], + trans_std, + part_size); + } else { + params = ngraph::builder::makeParams(ngPrc, {dataShape, roisShape, offsetsShape}); + inputs = ngraph::helpers::convert2OutputVector( + ngraph::helpers::castOps2Nodes(params)); + defomablePSROIPooling = std::make_shared(inputs[0], + inputs[1], + inputs[2], + outputDim, + spatialScale_, + groupSize, + mode, + spatialBinsXY[0], + spatialBinsXY[1], + trans_std, + part_size); + } + + ngraph::ResultVector results{std::make_shared(defomablePSROIPooling)}; + function = std::make_shared(results, params, "deformable_psroi_pooling"); + } +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py index 123ba098c7e..f2d02038c9a 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py @@ -20,6 +20,7 @@ VERIFIED_OP_REFERENCES = [ 'Convolution-1', 'Constant-1', 'DeformableConvolution-1', + 'DeformablePSROIPooling-1', 'DetectionOutput-1', 'Divide-1', 'ExperimentalDetectronDetectionOutput-6', diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/deformable_psroi_pooling.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/deformable_psroi_pooling.hpp new file mode 100644 index 00000000000..8974687724c --- /dev/null +++ b/ngraph/core/reference/include/ngraph/runtime/reference/deformable_psroi_pooling.hpp @@ -0,0 +1,231 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +// DeformablePSROIPooling implementation was inspired by +// https://github.com/msracver/Deformable-ConvNets +// Copyright (c) 2017 Microsoft +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include +#include + +#include "clamp.hpp" +#include "ngraph/shape.hpp" + +namespace ngraph +{ + namespace runtime + { + namespace reference + { + template + void deformable_psroi_pooling(const T* data_input, + const Shape& data_input_shape, + const T* rois_input, + const Shape& rois_input_shape, + const T* offsets_input, + const Shape& offsets_input_shape, + T* output, + const Shape& output_shape, + const std::string& mode_str, + const float spatial_scale, + const int64_t spatial_bins_x, + const int64_t spatial_bins_y, + const float trans_std, + const int64_t part_size) + { + const size_t channels_in = data_input_shape[1]; + const size_t height_in = data_input_shape[2]; + const size_t width_in = data_input_shape[3]; + + const size_t rois_count = output_shape[0]; + const size_t channels_out = output_shape[1]; + const size_t height_out = output_shape[2]; + const size_t width_out = output_shape[3]; + + std::fill(output, output + shape_size(output_shape), T{0}); + + // Single ROI is described by (batch_id, x1, y1, x2, y2) + const size_t roi_attrs_count = 5; + + for (size_t roi_idx = 0; roi_idx < rois_count; ++roi_idx) + { + // Pointer to the beginning of the ROI coords tuple + const T* roi = rois_input + roi_idx * roi_attrs_count; + + // Index of the corresponding input batch + int64_t roi_batch_id = roi[0]; + if (roi_batch_id < 0) + continue; + + // Left top ROI corner + const float roi_x1 = + static_cast(std::round(roi[1])) * spatial_scale - 0.5f; + const float roi_y1 = + static_cast(std::round(roi[2])) * spatial_scale - 0.5f; + // Right down ROI corner + const float roi_x2 = + static_cast(std::round(roi[3]) + 1.0f) * spatial_scale - 0.5f; + const float roi_y2 = + static_cast(std::round(roi[4]) + 1.0f) * spatial_scale - 0.5f; + + const float roi_width = std::max(roi_x2 - roi_x1, 0.1f); + const float roi_height = std::max(roi_y2 - roi_y1, 0.1f); + + const float bin_width = roi_width / static_cast(width_out); + const float bin_height = roi_height / static_cast(height_out); + + size_t c_idx_in = 0; + for (size_t c_idx_out = 0; c_idx_out < channels_out; ++c_idx_out) + { + for (size_t h_idx_out = 0; h_idx_out < height_out; ++h_idx_out) + { + // Next bin is taken from the next input channel + for (size_t w_idx_out = 0; w_idx_out < width_out; + ++w_idx_out, ++c_idx_in) + { + const size_t out_value_idx = + ((roi_idx * channels_out + c_idx_out) * height_out + + h_idx_out) * + width_out + + w_idx_out; + + // Left top corner of bin + float bin_x1_idx = roi_x1 + w_idx_out * bin_width; + float bin_y1_idx = roi_y1 + h_idx_out * bin_height; + + // Take offsets from optional input + if (offsets_input != nullptr && offsets_input_shape.size() == 4) + { + const auto num_coords = 2; // (x, y) + const size_t coords_sub_channels = + offsets_input_shape[1] / num_coords; + const size_t class_sub_channels = + channels_out / coords_sub_channels; + const size_t roi_channel_idx = c_idx_out / class_sub_channels; + + const size_t off_bin_w_idx = w_idx_out * part_size / width_out; + const size_t off_bin_h_idx = h_idx_out * part_size / height_out; + + const size_t offsets_channel_idx = + (roi_idx * coords_sub_channels + roi_channel_idx) * + num_coords; + + const size_t x_offset_idx = + (offsets_channel_idx * part_size + off_bin_h_idx) * + part_size + + off_bin_w_idx; + + const size_t y_offset_idx = + ((offsets_channel_idx + 1) * part_size + off_bin_h_idx) * + part_size + + off_bin_w_idx; + + T x_offset_value = offsets_input[x_offset_idx]; + T y_offset_value = offsets_input[y_offset_idx]; + + x_offset_value *= trans_std; + y_offset_value *= trans_std; + + // Move bin position by normalized offset values + bin_x1_idx += (x_offset_value * roi_width); + bin_y1_idx += (y_offset_value * roi_height); + } + + // Each bin is divided into sub-bins + // Values of sub-bins are calculated by bilinear interpolation + // Value of single bin is average of its sub-bins + const float sub_bin_width = + bin_width / static_cast(spatial_bins_x); + const float sub_bin_height = + bin_height / static_cast(spatial_bins_y); + + T sub_bins_val_sum = 0; + size_t legit_sub_bin_count = 0; + for (int sub_bin_h_idx = 0; sub_bin_h_idx < spatial_bins_y; + ++sub_bin_h_idx) + { + float sub_bin_y1_idx = + bin_y1_idx + sub_bin_h_idx * sub_bin_height; + if (sub_bin_y1_idx < -0.5 || sub_bin_y1_idx > height_in - 0.5) + continue; + + for (int sub_bin_w_idx = 0; sub_bin_w_idx < spatial_bins_x; + ++sub_bin_w_idx) + { + float sub_bin_x1_idx = + bin_x1_idx + sub_bin_w_idx * sub_bin_width; + if (sub_bin_x1_idx < -0.5 || + sub_bin_x1_idx > width_in - 0.5) + continue; + + clamp(&sub_bin_x1_idx, + &sub_bin_x1_idx, + 0.f, + width_in - 1.f, + 1); + clamp(&sub_bin_y1_idx, + &sub_bin_y1_idx, + 0.f, + height_in - 1.f, + 1); + + // Calculate value for sub-bin by bilinear interpolation + const int64_t left_x = + static_cast(std::floor(sub_bin_x1_idx)); + const int64_t right_x = + static_cast(std::ceil(sub_bin_x1_idx)); + const int64_t top_y = + static_cast(std::floor(sub_bin_y1_idx)); + const int64_t bottom_y = + static_cast(std::ceil(sub_bin_y1_idx)); + + const T* data_channel_ptr = + data_input + (roi_batch_id * channels_in + c_idx_in) * + height_in * width_in; + + const T top_left_sample = + data_channel_ptr[top_y * width_in + left_x]; + const T top_right_sample = + data_channel_ptr[top_y * width_in + right_x]; + const T bottom_left_sample = + data_channel_ptr[bottom_y * width_in + left_x]; + const T bottom_right_sample = + data_channel_ptr[bottom_y * width_in + right_x]; + + const float delta_left_x = + std::fabs(sub_bin_x1_idx - left_x); + const float delta_top_y = std::fabs(sub_bin_y1_idx - top_y); + + const T top_interp = + top_left_sample + + (top_right_sample - top_left_sample) * delta_left_x; + const T bottom_interp = + bottom_left_sample + + (bottom_right_sample - bottom_left_sample) * + delta_left_x; + + const T sub_bin_value = + top_interp + (bottom_interp - top_interp) * delta_top_y; + + legit_sub_bin_count++; + sub_bins_val_sum += sub_bin_value; + } + } + // Calculate average of sub_bin values for single ROI bin + if (legit_sub_bin_count != 0) + { + output[out_value_idx] = sub_bins_val_sum / legit_sub_bin_count; + } + } + } + } + } + } + } // namespace reference + } // namespace runtime +} // namespace ngraph diff --git a/ngraph/core/src/op/deformable_psroi_pooling.cpp b/ngraph/core/src/op/deformable_psroi_pooling.cpp index 01fd57610d9..651d38694ee 100644 --- a/ngraph/core/src/op/deformable_psroi_pooling.cpp +++ b/ngraph/core/src/op/deformable_psroi_pooling.cpp @@ -103,6 +103,9 @@ void op::v1::DeformablePSROIPooling::validate_and_infer_types() NODE_VALIDATION_CHECK( this, m_group_size > 0, "Value of `group_size` attribute has to be greater than 0 "); + NODE_VALIDATION_CHECK( + this, m_output_dim > 0, "Value of `output_dim` attribute has to be greater than 0 "); + int64_t output_rank = 4; std::vector output_dim_vec(output_rank, Dimension::dynamic()); if (box_coords_pshape.rank().is_static()) diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index ea68af8da22..835c020e1c4 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -216,6 +216,7 @@ set(SRC visitors/op/constant.cpp visitors/op/convert.cpp visitors/op/cum_sum.cpp + visitors/op/deformable_psroi_pooling.cpp visitors/op/detection_output.cpp visitors/op/elu.cpp visitors/op/extractimagepatches.cpp @@ -336,6 +337,7 @@ set(MULTI_TEST_SRC backend/ctc_greedy_decoder.in.cpp backend/ctc_greedy_decoder_seq_len.in.cpp backend/cum_sum.in.cpp + backend/deformable_psroi_pooling.in.cpp backend/detection_output.in.cpp backend/dft.in.cpp backend/divide.in.cpp diff --git a/ngraph/test/backend/deformable_psroi_pooling.in.cpp b/ngraph/test/backend/deformable_psroi_pooling.in.cpp new file mode 100644 index 00000000000..0ad191ff5b9 --- /dev/null +++ b/ngraph/test/backend/deformable_psroi_pooling.in.cpp @@ -0,0 +1,689 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" + +#include "ngraph/op/deformable_psroi_pooling.hpp" +#include "util/engine/test_engines.hpp" +#include "util/test_case.hpp" +#include "util/test_control.hpp" + +using namespace ngraph; + +static std::string s_manifest = "${MANIFEST}"; +using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_offset_00) +{ + const float spatial_scale = 0.0625; + const int64_t group_size = 2; + const size_t channels_in = 16; + size_t output_dim = channels_in / (group_size * group_size); // 4 + + size_t rois_count = 2; + + auto data_shape = Shape{1, channels_in, 2, 2}; + auto rois_shape = Shape{rois_count, 5}; + auto offsets_shape = Shape{rois_count, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size); + + Shape output_shape{rois_count, output_dim, group_size, group_size}; + // ASSERT_EQ(def_psroi_pool->get_output_shape(0), (output_shape)); + + std::vector data_values(shape_size(data_shape)); + std::iota(data_values.begin(), data_values.end(), 0); + // std::fill(data_values.begin(), data_values.end(), 0.1); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 1, + 2, + 4, + 6, + + 0, + 0, + 3, + 10, + 4, + }; + std::vector offsets_values(shape_size(offsets_shape)); + std::fill(offsets_values.begin(), offsets_values.end(), 0.0); + + std::vector expected_output_values{// First ROI + 0, 4, + 8, 12, + + 16, 20, + 24, 28, + + 32, 36, + 40, 44, + + 48, 52, + 56, 60, + + // Second ROI + 0, 4, + 8, 12, + + 16, 20, + 24, 28, + + 32, 36, + 40, 44, + + 48, 52, + 56, 60}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + test.add_input(offsets_values); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_offset_0p2) +{ + const float spatial_scale = 0.0625; + const int64_t group_size = 2; + const size_t channels_in = 16; + size_t output_dim = channels_in / (group_size * group_size); // 4 + + size_t rois_count = 2; + + auto data_shape = Shape{1, channels_in, 2, 2}; + auto rois_shape = Shape{rois_count, 5}; + auto offsets_shape = Shape{rois_count, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size); + + Shape output_shape{rois_count, output_dim, group_size, group_size}; + + std::vector data_values(shape_size(data_shape)); + std::iota(data_values.begin(), data_values.end(), 0); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 1, + 2, + 4, + 6, + + 0, + 0, + 3, + 10, + 4, + }; + std::vector offsets_values(shape_size(offsets_shape)); + std::fill(offsets_values.begin(), offsets_values.end(), 0.2); + + std::vector expected_output_values{// First ROI + 0, 4, + 8, 12, + + 16, 20, + 24, 28, + + 32, 36, + 40, 44, + + 48, 52, + 56, 60, + + // Second ROI + 0, 4, + 8, 12, + + 16, 20, + 24, 28, + + 32, 36, + 40, 44, + + 48, 52, + 56, 60}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + test.add_input(offsets_values); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_offset_0p5) +{ + const float spatial_scale = 0.0625; + const int64_t group_size = 2; + const size_t channels_in = 16; + size_t output_dim = channels_in / (group_size * group_size); // 4 + + size_t rois_count = 2; + + auto data_shape = Shape{1, channels_in, 2, 2}; + auto rois_shape = Shape{rois_count, 5}; + auto offsets_shape = Shape{rois_count, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size); + + Shape output_shape{rois_count, output_dim, group_size, group_size}; + + std::vector data_values(shape_size(data_shape)); + std::iota(data_values.begin(), data_values.end(), 0); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 1, + 2, + 4, + 6, + + 0, + 5, + 3, + 10, + 4, + }; + std::vector offsets_values(shape_size(offsets_shape)); + std::fill(offsets_values.begin(), offsets_values.end(), 0.5); + + std::vector expected_output_values{ + // First ROI + 0, 4, + 8, 12, + + 16, 20, + 24, 28, + + 32, 36, + 40, 44, + + 48, 52, + 56, 60, + + // Second ROI + 0, 4.1875, + 8, 12.1875, + + 16, 20.1875, + 24, 28.1875, + + 32, 36.1875, + 40, 44.1875, + + 48, 52.1875, + 56, 60.1875}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + test.add_input(offsets_values); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_roi_oversize) +{ + const float spatial_scale = 0.0625; + const int64_t group_size = 2; + const size_t channels_in = 16; + size_t output_dim = channels_in / (group_size * group_size); // 4 + + size_t rois_count = 2; + + auto data_shape = Shape{1, channels_in, 2, 2}; + auto rois_shape = Shape{rois_count, 5}; + auto offsets_shape = Shape{rois_count, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size); + + Shape output_shape{rois_count, output_dim, group_size, group_size}; + + std::vector data_values(shape_size(data_shape)); + std::iota(data_values.begin(), data_values.end(), 0); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 10, + 10, + 20, + 20, + + 0, + 100, + 100, + 200, + 200, + }; + std::vector offsets_values(shape_size(offsets_shape)); + std::fill(offsets_values.begin(), offsets_values.end(), 0.0); + + std::vector expected_output_values{ + 0.375, 4.71875, 9.0625, 13.40625, + 16.375, 20.71875, 25.0625, 29.40625, + 32.375, 36.71875, 41.0625, 45.40625, + 48.375, 52.71875, 57.0625, 61.40625, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + test.add_input(offsets_values); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_no_offset_input) +{ + const float spatial_scale = 1; + const int64_t group_size = 2; + const size_t spatial_bins_x = 1; + const size_t spatial_bins_y = 1; + const float trans_std = 1.0; + const int64_t part_size = group_size; + + const size_t batch_in = 1; + const size_t channels_in = 8; + const size_t width_in = 3; + const size_t height_in = 3; + + size_t output_dim = channels_in / (group_size * group_size); // 2 + + const auto rois_dim = 1; + + auto data_shape = Shape{batch_in, channels_in, height_in, width_in}; + auto rois_shape = Shape{rois_dim, 5}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, output_dim, spatial_scale, group_size, "bilinear_deformable", spatial_bins_x, spatial_bins_y, trans_std, part_size); + + Shape output_shape{rois_dim, output_dim, group_size, group_size}; + + std::vector data_values(shape_size(data_shape)); + std::iota(data_values.begin(), data_values.end(), 0); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 1, + 1, + 2, + 2, + }; + + std::vector expected_output_values{2.0, 12.0, 23.0, 33.0, 38.0, 48.0, 59.0, 69.0}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_offset_zero) +{ + const float spatial_scale = 1; + const int64_t group_size = 2; + const size_t spatial_bins_x = 1; + const size_t spatial_bins_y = 1; + const float trans_std = 1.0; + const int64_t part_size = group_size; + + const size_t batch_in = 1; + const size_t channels_in = 8; + const size_t width_in = 3; + const size_t height_in = 3; + + size_t output_dim = channels_in / (group_size * group_size); // 2 + + const auto rois_dim = 1; + + auto data_shape = Shape{batch_in, channels_in, height_in, width_in}; + auto rois_shape = Shape{rois_dim, 5}; + auto offsets_shape = Shape{rois_dim, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size, "bilinear_deformable", spatial_bins_x, spatial_bins_y, trans_std, part_size); + + Shape output_shape{rois_dim, output_dim, group_size, group_size}; + + std::vector data_values(shape_size(data_shape)); + std::iota(data_values.begin(), data_values.end(), 0); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 1, + 1, + 2, + 2, + }; + + + std::vector offsets_values(shape_size(offsets_shape)); + std::fill(offsets_values.begin(), offsets_values.end(), 0.0); + + std::vector expected_output_values{2.0, 12.0, 23.0, 33.0, 38.0, 48.0, 59.0, 69.0}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + test.add_input(offsets_values); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_offset_01) +{ + const float spatial_scale = 1; + const int64_t group_size = 2; + const size_t spatial_bins_x = 1; + const size_t spatial_bins_y = 1; + const float trans_std = 1.0; + const int64_t part_size = group_size; + + const size_t batch_in = 1; + const size_t channels_in = 8; + const size_t width_in = 3; + const size_t height_in = 3; + + size_t output_dim = channels_in / (group_size * group_size); // 2 + + const auto rois_dim = 1; + + auto data_shape = Shape{batch_in, channels_in, height_in, width_in}; + auto rois_shape = Shape{rois_dim, 5}; + auto offsets_shape = Shape{rois_dim, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size, + "bilinear_deformable", spatial_bins_x, spatial_bins_y, trans_std, part_size); + + Shape output_shape{rois_dim, output_dim, group_size, group_size}; + + std::vector data_values(shape_size(data_shape)); + std::iota(data_values.begin(), data_values.end(), 0); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 1, + 1, + 2, + 2, + }; + + + std::vector offsets_values(shape_size(offsets_shape)); + std::fill(offsets_values.begin(), offsets_values.end(), 0.1); + + std::vector expected_output_values{2.8, 12.8, 23.8, 33.8, 38.8, 48.8, 59.8, 69.8}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + test.add_input(offsets_values); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_offset_05) +{ + const float spatial_scale = 1; + const int64_t group_size = 2; + const size_t spatial_bins_x = 1; + const size_t spatial_bins_y = 1; + const float trans_std = 1.0; + const int64_t part_size = group_size; + + const size_t batch_in = 1; + const size_t channels_in = 8; + const size_t width_in = 3; + const size_t height_in = 3; + + size_t output_dim = channels_in / (group_size * group_size); // 2 + + const auto rois_dim = 1; + + auto data_shape = Shape{batch_in, channels_in, height_in, width_in}; + auto rois_shape = Shape{rois_dim, 5}; + auto offsets_shape = Shape{rois_dim, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size, "bilinear_deformable", spatial_bins_x, spatial_bins_y, trans_std, part_size); + + Shape output_shape{rois_dim, output_dim, group_size, group_size}; + + std::vector data_values(shape_size(data_shape)); + std::iota(data_values.begin(), data_values.end(), 0); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 1, + 1, + 2, + 2, + }; + + + std::vector offsets_values(shape_size(offsets_shape)); + std::fill(offsets_values.begin(), offsets_values.end(), 0.5); + + std::vector expected_output_values{6., 15.5, 25.5, 35., 42., 51.5, 61.5, 71.}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + test.add_input(offsets_values); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_single_value) +{ + const float spatial_scale = 0.0625; + const int64_t group_size = 2; + const size_t channels_in = 16; + size_t output_dim = channels_in / (group_size * group_size); // 4 + + size_t rois_count = 1; + + auto data_shape = Shape{1, channels_in, 2, 2}; + auto rois_shape = Shape{rois_count, 5}; + auto offsets_shape = Shape{rois_count, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size); + + Shape output_shape{rois_count, output_dim, group_size, group_size}; + + std::vector data_values(shape_size(data_shape)); + std::fill(data_values.begin(), data_values.end(), 0.1); + + std::vector rois_data{ + // input_batch_id, x1, y1, x2, y2 + 0, + 10, + 10, + 10, + 10, + }; + + + std::vector offsets_values(shape_size(offsets_shape)); + std::fill(offsets_values.begin(), offsets_values.end(), 0.1); + + std::vector expected_output_values{0.1, 0.1, + 0.1, 0.1, + + 0.1, 0.1, + 0.1, 0.1, + + 0.1, 0.1, + 0.1, 0.1, + + 0.1, 0.1, + 0.1, 0.1}; + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(data_values); + test.add_input(rois_data); + test.add_input(offsets_values); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, deformable_psroi_pooling_single_value_big_shape) +{ +const int64_t output_dim = 112; + const float spatial_scale = 0.0625; + const int64_t group_size = 3; + + size_t rois_count = 2; + + auto data_shape = Shape{1, 1024, 63, 38}; + auto rois_shape = Shape{rois_count, 5}; + auto offsets_shape = Shape{rois_count, 2, group_size, group_size}; + + auto data_param = std::make_shared(element::f32, data_shape); + auto rois_param = std::make_shared(element::f32, rois_shape); + auto offsets_param = std::make_shared(element::f32, offsets_shape); + + auto def_psroi_pool = std::make_shared( + data_param, rois_param, offsets_param, output_dim, spatial_scale, group_size); + + Shape output_shape{rois_count, output_dim, group_size, group_size}; + + std::vector input_data(shape_size(data_shape)); + std::fill(input_data.begin(), input_data.end(), 0.1); + + std::vector input_rois{ + // input_batch_id, x1, y1, x2, y2 + 0, + 1, + 2, + 4, + 6, + + 0, + 0, + 3, + 10, + 4, + }; + + std::vector input_offsets(shape_size(offsets_shape)); + std::fill(input_offsets.begin(), input_offsets.end(), 0.0); + + std::vector expected_output_values(shape_size(output_shape)); + std::fill(expected_output_values.begin(), expected_output_values.end(), 0.1); + + auto f = + std::make_shared(def_psroi_pool, + ParameterVector{data_param, rois_param, offsets_param}); + + auto test = test::TestCase(f); + test.add_input(input_data); + test.add_input(input_rois); + test.add_input(input_offsets); + + test.add_expected_output(output_shape, expected_output_values); + test.run(); +} diff --git a/ngraph/test/runtime/interpreter/evaluates_map.cpp b/ngraph/test/runtime/interpreter/evaluates_map.cpp index 1fc9a8d2f8f..67515e5cf1e 100644 --- a/ngraph/test/runtime/interpreter/evaluates_map.cpp +++ b/ngraph/test/runtime/interpreter/evaluates_map.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -2259,6 +2260,56 @@ namespace return true; } + template + bool evaluate(const shared_ptr& op, + const HostTensorVector& outputs, + const HostTensorVector& inputs) + { + using T = typename element_type_traits::value_type; + NGRAPH_CHECK(inputs.size() > 1 && inputs[1]->get_shape().size() == 2, + "2D tensor must be provided as second input. "); + outputs[0]->set_shape({inputs[1]->get_shape()[0], + static_cast(op->get_output_dim()), + static_cast(op->get_group_size()), + static_cast(op->get_group_size())}); + + const bool has_offset_intput = inputs.size() == 3; + if (has_offset_intput) + { + runtime::reference::deformable_psroi_pooling(inputs[0]->get_data_ptr(), + inputs[0]->get_shape(), + inputs[1]->get_data_ptr(), + inputs[1]->get_shape(), + inputs[2]->get_data_ptr(), + inputs[2]->get_shape(), + outputs[0]->get_data_ptr(), + outputs[0]->get_shape(), + op->get_mode(), + op->get_spatial_scale(), + op->get_spatial_bins_x(), + op->get_spatial_bins_y(), + op->get_trans_std(), + op->get_part_size()); + } + else + { + runtime::reference::deformable_psroi_pooling(inputs[0]->get_data_ptr(), + inputs[0]->get_shape(), + inputs[1]->get_data_ptr(), + inputs[1]->get_shape(), + nullptr, + ngraph::Shape(), + outputs[0]->get_data_ptr(), + outputs[0]->get_shape(), + op->get_mode(), + op->get_spatial_scale(), + op->get_spatial_bins_x(), + op->get_spatial_bins_y(), + op->get_trans_std(), + op->get_part_size()); + } + return true; + } template bool evaluate(const shared_ptr& op, diff --git a/ngraph/test/runtime/interpreter/opset_int_tbl.hpp b/ngraph/test/runtime/interpreter/opset_int_tbl.hpp index abf494d55d3..16907f55ff7 100644 --- a/ngraph/test/runtime/interpreter/opset_int_tbl.hpp +++ b/ngraph/test/runtime/interpreter/opset_int_tbl.hpp @@ -41,6 +41,7 @@ NGRAPH_OP(BinaryConvolution, ngraph::op::v1) NGRAPH_OP(ConvertLike, op::v1) NGRAPH_OP(Convolution, ngraph::op::v1) NGRAPH_OP(ConvolutionBackpropData, ngraph::op::v1) +NGRAPH_OP(DeformablePSROIPooling, ngraph::op::v1) NGRAPH_OP(GroupConvolution, ngraph::op::v1) NGRAPH_OP(GroupConvolutionBackpropData, ngraph::op::v1) NGRAPH_OP(DeformableConvolution, ngraph::op::v1) diff --git a/ngraph/test/type_prop/deformable_psroi_pooling.cpp b/ngraph/test/type_prop/deformable_psroi_pooling.cpp index 61474d800a5..d20552ca699 100644 --- a/ngraph/test/type_prop/deformable_psroi_pooling.cpp +++ b/ngraph/test/type_prop/deformable_psroi_pooling.cpp @@ -131,6 +131,33 @@ TEST(type_prop, deformable_psroi_pooling_invalid_group_size) } } +TEST(type_prop, deformable_psroi_pooling_invalid_output_dim) +{ + const float spatial_scale = 0.0625; + const auto rois_dim = 300; + const int64_t group_size = 3; + + try + { + const int64_t output_dim = -882; + + auto input_data = make_shared(element::f32, PartialShape{2, 7938, 63, 38}); + auto input_coords = make_shared(element::f32, PartialShape{rois_dim, 5}); + auto def_psroi_pool = make_shared( + input_data, input_coords, output_dim, spatial_scale, group_size); + + FAIL() << "Invalid output_dim not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), std::string("Value of `output_dim` attribute has to be greater than 0")); + } + catch (...) + { + FAIL() << "Unknown exception was thrown"; + } +} + TEST(type_prop, deformable_psroi_pooling_invalid_data_input_rank) { const float spatial_scale = 0.0625; diff --git a/ngraph/test/visitors/op/deformable_psroi_pooling.cpp b/ngraph/test/visitors/op/deformable_psroi_pooling.cpp new file mode 100644 index 00000000000..9512e51dec1 --- /dev/null +++ b/ngraph/test/visitors/op/deformable_psroi_pooling.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" + +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset1.hpp" + +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(attributes, deformable_psroi_pooling_op) +{ + NodeBuilder::get_ops().register_factory(); + auto input = make_shared(element::f32, Shape{2, 16, 67, 32}); + auto coords = make_shared(element::f32, Shape{300, 5}); + + const int output_dim = 4; + const float spatial_scale = 0.0625; + const int group_size = 2; + string mode = "bilinear_deformable"; + const int spatial_bins_x = 2; + const int spatial_bins_y = 3; + const float trans_std = 0.1; + const int part_size = 3; + + auto op = make_shared( + input, coords, output_dim, spatial_scale, group_size, mode, spatial_bins_x, spatial_bins_y, trans_std, part_size); + NodeBuilder builder(op); + auto g_op = as_type_ptr(builder.create()); + + EXPECT_EQ(g_op->get_output_dim(), op->get_output_dim()); + EXPECT_EQ(g_op->get_spatial_scale(), op->get_spatial_scale()); + EXPECT_EQ(g_op->get_group_size(), op->get_group_size()); + EXPECT_EQ(g_op->get_mode(), op->get_mode()); + EXPECT_EQ(g_op->get_spatial_bins_x(), op->get_spatial_bins_x()); + EXPECT_EQ(g_op->get_spatial_bins_y(), op->get_spatial_bins_y()); + EXPECT_EQ(g_op->get_trans_std(), op->get_trans_std()); + EXPECT_EQ(g_op->get_part_size(), op->get_part_size()); +} From 39fde540d2e11e350ec9ca4d6e391ba19a65dd94 Mon Sep 17 00:00:00 2001 From: Bartosz Lesniewski Date: Thu, 13 May 2021 06:45:29 +0200 Subject: [PATCH 44/99] Revise Unsqueeze op - op class (#5555) * revise unsqueeze op class * Added checks and tests for second input incorrect type and shape * Remove axes type constraints to keep backward compatibility --- ngraph/core/src/op/unsqueeze.cpp | 12 ++++--- ngraph/test/type_prop/unsqueeze.cpp | 51 +++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/ngraph/core/src/op/unsqueeze.cpp b/ngraph/core/src/op/unsqueeze.cpp index dd593d0920e..cc1cfa9da0a 100644 --- a/ngraph/core/src/op/unsqueeze.cpp +++ b/ngraph/core/src/op/unsqueeze.cpp @@ -34,23 +34,27 @@ void op::v0::Unsqueeze::validate_and_infer_types() const auto data_rank = data_partial_shape.rank(); const auto axes_constant = get_constant_from_source(input_value(1)); + auto axes_pshape = get_input_partial_shape(1); + + NODE_VALIDATION_CHECK(this, + axes_pshape.rank().compatible(0) || axes_pshape.rank().compatible(1), + "Second input (axes) should not be of rank higher than 1. Got: ", + axes_pshape.rank().get_length()); + if (data_rank.is_dynamic() || !axes_constant) { set_output_type(0, get_input_element_type(0), PartialShape::dynamic()); return; } - uint64_t data_rank_value = data_partial_shape.rank().get_length(); - - // Get value of axes from Constant const auto axes_values = axes_constant->cast_vector(); + uint64_t data_rank_value = data_partial_shape.rank().get_length(); const int64_t expanded_rank = data_rank_value + axes_values.size(); NODE_VALIDATION_CHECK(this, !axes_values.empty(), "'axes' input is mandatory"); auto normalized_axes = normalize_axes(this->description(), axes_values, expanded_rank); set axes(begin(normalized_axes), end(normalized_axes)); - vector output_shape{data_partial_shape}; for (auto axis : axes) { diff --git a/ngraph/test/type_prop/unsqueeze.cpp b/ngraph/test/type_prop/unsqueeze.cpp index 252e3139b73..c38ed797437 100644 --- a/ngraph/test/type_prop/unsqueeze.cpp +++ b/ngraph/test/type_prop/unsqueeze.cpp @@ -37,3 +37,54 @@ TEST(type_prop, unsqueeze_dynamic) Dimension::dynamic(), Dimension::dynamic()})); } + +TEST(type_prop, unsqueeze_incorrect_axes_shape) +{ + auto param = make_shared(element::f32, Shape{4, 1, 4, 1, 8}); + auto axes_node = + make_shared(element::u64, Shape{1, 1, 1}, vector{1}); + + try + { + auto unsqueeze = make_shared(param, axes_node); + FAIL() << "Unsqueeze axes invalid rank not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), + "Second input (axes) should not be of rank higher than 1"); + } + catch (...) + { + FAIL() << "Deduced type check failed for unexpected reason"; + } +} + +TEST(type_prop, unsqueeze_empty_axes) +{ + auto param = make_shared(element::f32, Shape{4, 1, 4, 1, 8}); + auto axes_node = make_shared(element::u64, Shape{0}, vector{}); + try + { + auto unsqueeze = make_shared(param, axes_node); + FAIL() << "Unsqueeze axes empty not detected"; + } + catch (const NodeValidationFailure& error) + { + EXPECT_HAS_SUBSTRING(error.what(), "'axes' input is mandatory"); + } + catch (...) + { + FAIL() << "Deduced type check failed for unexpected reason"; + } +} + +TEST(type_prop, unsqueeze_dynamic_axes) +{ + auto param = make_shared(element::f32, Shape{4, 1, 4, 1, 8}); + auto axes_node = make_shared(element::u64, PartialShape::dynamic()); + + auto unsqueeze = make_shared(param, axes_node); + ASSERT_EQ(unsqueeze->get_element_type(), element::f32); + ASSERT_EQ(unsqueeze->get_output_partial_shape(0), PartialShape::dynamic()); +} \ No newline at end of file From 07a49184c0001ab609169b9f0755ce564cd543cb Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 13 May 2021 07:52:55 +0300 Subject: [PATCH 45/99] Fixed typo in length (#5611) --- docs/ops/movement/VariadicSplit_1.md | 2 +- .../legacy/ngraph_ops/lstm_sequence_ie.hpp | 2 +- .../src/ngraph_ops/gru_sequence_ie.cpp | 6 +++--- .../src/ngraph_ops/lstm_sequence_ie.cpp | 6 +++--- .../src/ngraph_ops/rnn_sequence_ie.cpp | 2 +- .../src/vpu/myriad_plugin/myriad_metrics.cpp | 4 ++-- .../onnx_reader/onnx_reader_external_data.cpp | 2 +- .../convert_sequences_to_sequences_ie_test.cpp | 4 ++-- .../single_layer_tests/gru_sequence.cpp | 2 +- .../single_layer_tests/loop.cpp | 2 +- .../single_layer_tests/lstm_sequence.cpp | 2 +- .../single_layer_tests/rnn_sequence.cpp | 2 +- .../single_layer_tests/tensor_iterator.cpp | 2 +- .../cpu/single_layer_tests/gru_sequence.cpp | 10 +++++----- .../cpu/single_layer_tests/lstm_sequence.cpp | 8 ++++---- .../cpu/single_layer_tests/rnn_sequence.cpp | 10 +++++----- .../single_layer_tests/gru_sequence.cpp | 2 +- .../single_layer_tests/lstm_sequence.cpp | 2 +- .../single_layer_tests/rnn_sequence.cpp | 2 +- .../single_layer/ctc_loss.hpp | 2 +- .../src/single_layer/gru_sequence.cpp | 14 +++++++------- .../src/single_layer/lstm_sequence.cpp | 14 +++++++------- .../src/single_layer/rnn_sequence.cpp | 14 +++++++------- .../src/single_layer/tensor_iterator.cpp | 16 ++++++++-------- .../graph_optimizer/prepare_buffer_fusing.cpp | 6 +++--- inference-engine/thirdparty/mkl-dnn | 2 +- .../movidius/mvnc/tests/mvnc_no_boot_tests.cpp | 8 ++++---- .../movidius/mvnc/tests/mvnc_tests_common.cpp | 8 ++++---- .../movidius/mvnc/tests/mvnc_tests_usb.cpp | 12 ++++++------ .../thirdparty/pugixml/src/pugixml.cpp | 8 ++++---- ngraph/core/include/ngraph/op/ctc_loss.hpp | 2 +- ngraph/core/include/ngraph/op/lstm_sequence.hpp | 6 +++--- ngraph/frontend/onnx_import/src/op/slice.cpp | 2 +- .../src/utils/tensor_external_data.cpp | 16 ++++++++-------- .../src/utils/tensor_external_data.hpp | 2 +- .../tests/test_ngraph/test_data_movement.py | 6 +++--- ngraph/test/backend/reverse_sequence.in.cpp | 16 ++++++++-------- .../test/onnx/onnx_import_external_data.in.cpp | 4 ++-- ngraph/test/type_prop/reverse_sequence.cpp | 14 +++++++------- 39 files changed, 122 insertions(+), 122 deletions(-) diff --git a/docs/ops/movement/VariadicSplit_1.md b/docs/ops/movement/VariadicSplit_1.md index 50bbbd6e959..87c9ac67b65 100644 --- a/docs/ops/movement/VariadicSplit_1.md +++ b/docs/ops/movement/VariadicSplit_1.md @@ -26,7 +26,7 @@ Where D is the rank of input tensor `data`. The sum of elements in `split_length * **2**: `axis`. Axis along `data` to split. A scalar of type `T2` with value from range `-rank(data) .. rank(data)-1`. Negative values address dimensions from the end. **Required.** -* **3**: `split_lengths`. A list containing the dimension values of each output tensor shape along the split `axis`. A 1D tensor of type `T2`. The number of elements in `split_lengths` determines the number of outputs. The sum of elements in `split_lengths` must match `data.shape[axis]`. In addition `split_lenghts` can contain a single `-1` element, which means, all remaining items along specified `axis` that are not consumed by other parts. **Required.** +* **3**: `split_lengths`. A list containing the dimension values of each output tensor shape along the split `axis`. A 1D tensor of type `T2`. The number of elements in `split_lengths` determines the number of outputs. The sum of elements in `split_lengths` must match `data.shape[axis]`. In addition `split_lengths` can contain a single `-1` element, which means, all remaining items along specified `axis` that are not consumed by other parts. **Required.** **Outputs** diff --git a/inference-engine/src/legacy_api/include/legacy/ngraph_ops/lstm_sequence_ie.hpp b/inference-engine/src/legacy_api/include/legacy/ngraph_ops/lstm_sequence_ie.hpp index 68f2688a57f..641f93bd063 100644 --- a/inference-engine/src/legacy_api/include/legacy/ngraph_ops/lstm_sequence_ie.hpp +++ b/inference-engine/src/legacy_api/include/legacy/ngraph_ops/lstm_sequence_ie.hpp @@ -24,7 +24,7 @@ public: LSTMSequenceIE(const Output &X, const Output &H_t, const Output &C_t, - const Output &seq_lenghts, + const Output &seq_lengths, const Output &WR, const Output &B, size_t hidden_size, diff --git a/inference-engine/src/legacy_api/src/ngraph_ops/gru_sequence_ie.cpp b/inference-engine/src/legacy_api/src/ngraph_ops/gru_sequence_ie.cpp index 296e65a786d..1920221c476 100644 --- a/inference-engine/src/legacy_api/src/ngraph_ops/gru_sequence_ie.cpp +++ b/inference-engine/src/legacy_api/src/ngraph_ops/gru_sequence_ie.cpp @@ -16,7 +16,7 @@ NGRAPH_RTTI_DEFINITION(op::GRUSequenceIE, "GRUSequenceIE", 4); op::GRUSequenceIE::GRUSequenceIE(const Output& X, const Output& H_t, - const Output& seq_lenghts, + const Output& seq_lengths, const Output& WR, const Output& B, std::size_t hidden_size, @@ -27,7 +27,7 @@ op::GRUSequenceIE::GRUSequenceIE(const Output& X, float clip, bool linear_before_reset, int64_t seq_axis) - : RNNCellBase({X, H_t, seq_lenghts, WR, B}, hidden_size, clip, activations, activations_alpha, activations_beta), + : RNNCellBase({X, H_t, seq_lengths, WR, B}, hidden_size, clip, activations, activations_alpha, activations_beta), m_direction(direction), m_linear_before_reset(linear_before_reset), m_seq_axis(seq_axis) { @@ -50,7 +50,7 @@ void op::GRUSequenceIE::validate_and_infer_types() { auto b_pshape = get_input_partial_shape(4); std::vector pshapes = {x_pshape, h_state_pshape, seq_lengths_pshape, wr_pshape, b_pshape}; - std::vector in_names = {"X", "H", "seq_lenghts", "WR", "B"}; + std::vector in_names = {"X", "H", "seq_lengths", "WR", "B"}; // num_direction dimension should be squeezed, we don't support bidirectional case std::vector ranks = {3, 2, 1, 2, 1}; for (size_t i = 0; i < pshapes.size(); ++i) { diff --git a/inference-engine/src/legacy_api/src/ngraph_ops/lstm_sequence_ie.cpp b/inference-engine/src/legacy_api/src/ngraph_ops/lstm_sequence_ie.cpp index e0aa3f3ef77..b32ae8205ef 100644 --- a/inference-engine/src/legacy_api/src/ngraph_ops/lstm_sequence_ie.cpp +++ b/inference-engine/src/legacy_api/src/ngraph_ops/lstm_sequence_ie.cpp @@ -17,7 +17,7 @@ NGRAPH_RTTI_DEFINITION(op::LSTMSequenceIE, "LSTMSequenceIE", 5); op::LSTMSequenceIE::LSTMSequenceIE(const Output &X, const Output &H_t, const Output &C_t, - const Output &seq_lenghts, + const Output &seq_lengths, const Output &WR, const Output &B, std::size_t hidden_size, @@ -27,7 +27,7 @@ op::LSTMSequenceIE::LSTMSequenceIE(const Output &X, const std::vector &activations_beta, float clip, int64_t seq_axis) - : RNNCellBase({X, H_t, C_t, seq_lenghts, WR, B}, hidden_size, clip, activations, activations_alpha, activations_beta), + : RNNCellBase({X, H_t, C_t, seq_lengths, WR, B}, hidden_size, clip, activations, activations_alpha, activations_beta), m_direction(direction), m_seq_axis(seq_axis) { constructor_validate_and_infer_types(); @@ -52,7 +52,7 @@ void op::LSTMSequenceIE::validate_and_infer_types() { std::vector pshapes = {x_pshape, h_state_pshape, c_state_pshape, seq_lengths_pshape, wr_pshape, b_pshape}; - std::vector in_names = {"X", "H", "C", "seq_lenghts", "WR", "B"}; + std::vector in_names = {"X", "H", "C", "seq_lengths", "WR", "B"}; // num_direction dimension should be squeezed, we don't support bidirectional case std::vector ranks = {3, 2, 2, 1, 2, 1}; for (size_t i = 0; i < pshapes.size(); ++i) { diff --git a/inference-engine/src/legacy_api/src/ngraph_ops/rnn_sequence_ie.cpp b/inference-engine/src/legacy_api/src/ngraph_ops/rnn_sequence_ie.cpp index 6b0a1c97dd4..168885de406 100644 --- a/inference-engine/src/legacy_api/src/ngraph_ops/rnn_sequence_ie.cpp +++ b/inference-engine/src/legacy_api/src/ngraph_ops/rnn_sequence_ie.cpp @@ -48,7 +48,7 @@ void op::RNNSequenceIE::validate_and_infer_types() { auto b_pshape = get_input_partial_shape(4); std::vector pshapes = {x_pshape, h_state_pshape, seq_lengths_pshape, wr_pshape, b_pshape}; - std::vector in_names = {"X", "H", "seq_lenghts", "WR", "B"}; + std::vector in_names = {"X", "H", "seq_lengths", "WR", "B"}; // num_direction dimension should be squeezed, we don't support bidirectional case std::vector ranks = {3, 2, 1, 2, 1}; for (size_t i = 0; i < pshapes.size(); ++i) { diff --git a/inference-engine/src/vpu/myriad_plugin/myriad_metrics.cpp b/inference-engine/src/vpu/myriad_plugin/myriad_metrics.cpp index 3d314cc873c..fc022ff4184 100644 --- a/inference-engine/src/vpu/myriad_plugin/myriad_metrics.cpp +++ b/inference-engine/src/vpu/myriad_plugin/myriad_metrics.cpp @@ -81,13 +81,13 @@ std::vector MyriadMetrics::AvailableDevicesNames( std::string MyriadMetrics::FullName(std::string deviceName) const { std::string nameDelimiter("-ma"); - unsigned int indexLenght = 4; + unsigned int indexLength = 4; unsigned int placeOfTypeId = 2; auto indexStr = deviceName; indexStr.erase(0, indexStr.find(nameDelimiter) + nameDelimiter.length()); - if (indexLenght != indexStr.length()) { + if (indexLength != indexStr.length()) { return deviceName; } else { auto myriadId = std::string(1, indexStr[placeOfTypeId]); diff --git a/inference-engine/tests/functional/inference_engine/onnx_reader/onnx_reader_external_data.cpp b/inference-engine/tests/functional/inference_engine/onnx_reader/onnx_reader_external_data.cpp index 3a72dbf6e80..2ae931d76b8 100644 --- a/inference-engine/tests/functional/inference_engine/onnx_reader/onnx_reader_external_data.cpp +++ b/inference-engine/tests/functional/inference_engine/onnx_reader/onnx_reader_external_data.cpp @@ -64,7 +64,7 @@ TEST(ONNX_Reader_Tests, ImportModelWithExternalDataFromStringException) { EXPECT_PRED_FORMAT2( testing::IsSubstring, - std::string("data/tensor.data, offset: 0, data_lenght: 0, sha1_digest: 0)"), + std::string("data/tensor.data, offset: 0, data_length: 0, sha1_digest: 0)"), e.what()); } catch(...) { diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_sequences_to_sequences_ie_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_sequences_to_sequences_ie_test.cpp index 30e69d7f7b7..76b4cce3f4c 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_sequences_to_sequences_ie_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_sequences_to_sequences_ie_test.cpp @@ -229,7 +229,7 @@ TEST(TransformationTests, LSTMSequenceConversionTest) { ngraph::Shape{batch_size, num_directions, hidden_size}); const auto C_t = std::make_shared(ngraph::element::f32, ngraph::Shape{batch_size, num_directions, hidden_size}); - const auto seq_lenghts = std::make_shared(ngraph::element::f32, + const auto seq_lengths = std::make_shared(ngraph::element::f32, ngraph::Shape{batch_size}); const auto B = std::make_shared(ngraph::element::f32, ngraph::Shape{num_directions, @@ -245,7 +245,7 @@ TEST(TransformationTests, LSTMSequenceConversionTest) { auto sequence_ie = std::make_shared(X, in_1, in_2, - seq_lenghts, + seq_lengths, in_3, in_4, sequence->get_hidden_size(), diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp index 7e3dea8b04f..5521023a192 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp @@ -16,7 +16,7 @@ namespace { ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; - // output values increase rapidly without clip, so use only seq_lenghts = 2 + // output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector seq_lengths_clip_non_zero{20}; std::vector batch{10}; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/loop.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/loop.cpp index ad294a4ce1f..1a14f9a97e4 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/loop.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/loop.cpp @@ -9,7 +9,7 @@ using namespace LayerTestsDefinitions; namespace { - // without clip values increase rapidly, so use only seq_lenghts = 2 + // without clip values increase rapidly, so use only seq_lengths = 2 std::vector execute_first_iteration{true}; std::vector is_body_condition_const{true/*, false*/}; std::vector body_condition{true/*, false*/}; // works only if is_body_condition_const == true diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp index 1fbe1190a76..3ccbddc8f31 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp @@ -16,7 +16,7 @@ namespace { ngraph::helpers::SequenceTestsMode::PURE_SEQ, ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM}; - // output values increase rapidly without clip, so use only seq_lenghts = 2 + // output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector seq_lengths_clip_non_zero{20}; std::vector batch{10}; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp index 0805ff960d6..3db31d471c5 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp @@ -16,7 +16,7 @@ namespace { ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; - // output values increase rapidly without clip, so use only seq_lenghts = 2 + // output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector seq_lengths_clip_non_zero{20}; std::vector batch{1, 10}; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/tensor_iterator.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/tensor_iterator.cpp index 2531a6668c4..2a551b695f9 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/tensor_iterator.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/tensor_iterator.cpp @@ -11,7 +11,7 @@ using namespace LayerTestsDefinitions; namespace { std::vector should_decompose = {true, false}; - // output values increase rapidly without clip, so use only seq_lenghts = 2 + // output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector seq_lengths_clip_non_zero{20}; std::vector batch{1, 10}; diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp index b3f7b213136..55ece3f0a66 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp @@ -46,7 +46,7 @@ protected: CPUSpecificParams cpuParams; std::map additionalConfig; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size = 10; @@ -60,11 +60,11 @@ protected: std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(m_mode, seq_lenghts, batch, hidden_size, activations, clip, linear_before_reset, direction, netPrecision, targetDevice) = basicParamsSet; + std::tie(m_mode, seq_lengths, batch, hidden_size, activations, clip, linear_before_reset, direction, netPrecision, targetDevice) = basicParamsSet; size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; std::vector> inputShapes = { - {{batch, seq_lenghts, input_size}, + {{batch, seq_lengths, input_size}, {batch, num_directions, hidden_size}, {batch}, {num_directions, 3 * hidden_size, input_size}, @@ -89,7 +89,7 @@ protected: selectedType += "_"; selectedType += outPrc.name(); - m_max_seq_len = seq_lenghts; + m_max_seq_len = seq_lengths; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]}); if (m_mode == ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM @@ -174,7 +174,7 @@ CPUSpecificParams cpuParams{{ntc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"}; CPUSpecificParams cpuParamsBatchSizeOne{{ntc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"};; std::vector mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ}; -// output values increase rapidly without clip, so use only seq_lenghts = 2 +// output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector batch{10}; std::vector batch_size_one{1}; diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp index 538ca675a7f..234a579085c 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp @@ -47,7 +47,7 @@ protected: CPUSpecificParams cpuParams; std::map additionalConfig; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size; @@ -60,12 +60,12 @@ protected: std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(m_mode, seq_lenghts, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = basicParamsSet; + std::tie(m_mode, seq_lengths, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = basicParamsSet; size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; - m_max_seq_len = seq_lenghts; + m_max_seq_len = seq_lengths; std::vector> inputShapes = { - {{batch, seq_lenghts, input_size}, + {{batch, seq_lengths, input_size}, {batch, num_directions, hidden_size}, {batch, num_directions, hidden_size}, {batch}, diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp index 009dcdd01f2..6c7f873cc95 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp @@ -46,7 +46,7 @@ protected: CPUSpecificParams cpuParams; std::map additionalConfig; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size; @@ -59,11 +59,11 @@ protected: std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(m_mode, seq_lenghts, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = basicParamsSet; + std::tie(m_mode, seq_lengths, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = basicParamsSet; size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; std::vector> inputShapes = { - {{batch, seq_lenghts, input_size}, + {{batch, seq_lengths, input_size}, {batch, num_directions, hidden_size}, {batch}, {num_directions, hidden_size, input_size}, @@ -82,7 +82,7 @@ protected: selectedType += "_"; selectedType += outPrc.name(); - m_max_seq_len = seq_lenghts; + m_max_seq_len = seq_lengths; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]}); if (m_mode == ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM @@ -152,7 +152,7 @@ CPUSpecificParams cpuParams{{ntc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"}; CPUSpecificParams cpuParamsBatchSizeOne{{ntc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"}; std::vector mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ}; -// output values increase rapidly without clip, so use only seq_lenghts = 2 +// output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector batch{10}; std::vector batch_size_one{1}; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp index 9474335c2fe..d0033f4f473 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp @@ -16,7 +16,7 @@ namespace { ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; - // output values increase rapidly without clip, so use only seq_lenghts = 2 + // output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector seq_lengths_clip_non_zero{20}; std::vector batch{10}; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp index 01c28409301..d79cee69eea 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp @@ -16,7 +16,7 @@ std::vector mode{ngraph::helpers::SequenceTe ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; -// output values increase rapidly without clip, so use only seq_lenghts = 2 +// output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector seq_lengths_clip_non_zero{20}; std::vector batch{10}; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp index 10f888cec1e..718c1b6e771 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp @@ -16,7 +16,7 @@ std::vector mode{ngraph::helpers::SequenceTe ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; -// output values increase rapidly without clip, so use only seq_lenghts = 2 +// output values increase rapidly without clip, so use only seq_lengths = 2 std::vector seq_lengths_zero_clip{2}; std::vector seq_lengths_clip_non_zero{20}; std::vector batch{1, 10}; diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/ctc_loss.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/ctc_loss.hpp index bcf89fef2b7..7b8a67d95c4 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/ctc_loss.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/ctc_loss.hpp @@ -14,7 +14,7 @@ namespace LayerTestsDefinitions { typedef std::tuple< std::vector, // Logits shapes - std::vector, // logits lenght + std::vector, // logits length std::vector>, // labels std::vector, // labels length int, // blank index diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp index c89a1bc06e2..f43cca3ca6d 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp @@ -10,7 +10,7 @@ namespace LayerTestsDefinitions { std::string GRUSequenceTest::getTestCaseName(const testing::TestParamInfo &obj) { ngraph::helpers::SequenceTestsMode mode; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size = 10; @@ -22,7 +22,7 @@ namespace LayerTestsDefinitions { ngraph::op::RecurrentSequenceDirection direction; InferenceEngine::Precision netPrecision; std::string targetDevice; - std::tie(mode, seq_lenghts, batch, hidden_size, activations, clip, linear_before_reset, direction, netPrecision, + std::tie(mode, seq_lengths, batch, hidden_size, activations, clip, linear_before_reset, direction, netPrecision, targetDevice) = obj.param; std::vector> inputShapes = { {{batch, input_size}, {batch, hidden_size}, {batch, hidden_size}, {3 * hidden_size, input_size}, @@ -30,7 +30,7 @@ namespace LayerTestsDefinitions { }; std::ostringstream result; result << "mode=" << mode << "_"; - result << "seq_lenghts=" << seq_lenghts << "_"; + result << "seq_lengths=" << seq_lengths << "_"; result << "batch=" << batch << "_"; result << "hidden_size=" << hidden_size << "_"; result << "input_size=" << input_size << "_"; @@ -45,7 +45,7 @@ namespace LayerTestsDefinitions { void GRUSequenceTest::SetUp() { using namespace ngraph::helpers; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size = 10; @@ -56,15 +56,15 @@ namespace LayerTestsDefinitions { bool linear_before_reset; ngraph::op::RecurrentSequenceDirection direction; InferenceEngine::Precision netPrecision; - std::tie(m_mode, seq_lenghts, batch, hidden_size, activations, clip, linear_before_reset, direction, netPrecision, + std::tie(m_mode, seq_lengths, batch, hidden_size, activations, clip, linear_before_reset, direction, netPrecision, targetDevice) = this->GetParam(); size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; std::vector> inputShapes = { - {{batch, seq_lenghts, input_size}, {batch, num_directions, hidden_size}, {batch}, + {{batch, seq_lengths, input_size}, {batch, num_directions, hidden_size}, {batch}, {num_directions, 3 * hidden_size, input_size}, {num_directions, 3 * hidden_size, hidden_size}, {num_directions, (linear_before_reset ? 4 : 3) * hidden_size}}, }; - m_max_seq_len = seq_lenghts; + m_max_seq_len = seq_lengths; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]}); if (m_mode == SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM || diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/lstm_sequence.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/lstm_sequence.cpp index f26475d84eb..7bb4289ec73 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/lstm_sequence.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/lstm_sequence.cpp @@ -11,7 +11,7 @@ namespace LayerTestsDefinitions { std::string LSTMSequenceTest::getTestCaseName(const testing::TestParamInfo &obj) { ngraph::helpers::SequenceTestsMode mode; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size; @@ -22,7 +22,7 @@ namespace LayerTestsDefinitions { ngraph::op::RecurrentSequenceDirection direction; InferenceEngine::Precision netPrecision; std::string targetDevice; - std::tie(mode, seq_lenghts, batch, hidden_size, input_size, activations, clip, direction, netPrecision, + std::tie(mode, seq_lengths, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = obj.param; std::vector> inputShapes = { {{batch, input_size}, {batch, hidden_size}, {batch, hidden_size}, {4 * hidden_size, input_size}, @@ -30,7 +30,7 @@ namespace LayerTestsDefinitions { }; std::ostringstream result; result << "mode=" << mode << "_"; - result << "seq_lenghts=" << seq_lenghts << "_"; + result << "seq_lengths=" << seq_lengths << "_"; result << "batch=" << batch << "_"; result << "hidden_size=" << hidden_size << "_"; result << "input_size=" << input_size << "_"; @@ -46,7 +46,7 @@ namespace LayerTestsDefinitions { void LSTMSequenceTest::SetUp() { using namespace ngraph::helpers; using namespace ngraph::builder; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; @@ -57,12 +57,12 @@ namespace LayerTestsDefinitions { float clip; ngraph::op::RecurrentSequenceDirection direction; InferenceEngine::Precision netPrecision; - std::tie(m_mode, seq_lenghts, batch, hidden_size, input_size, activations, clip, direction, netPrecision, + std::tie(m_mode, seq_lengths, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = this->GetParam(); size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; - m_max_seq_len = seq_lenghts; + m_max_seq_len = seq_lengths; std::vector> inputShapes = { - {{batch, seq_lenghts, input_size}, {batch, num_directions, hidden_size}, {batch, num_directions, hidden_size}, + {{batch, seq_lengths, input_size}, {batch, num_directions, hidden_size}, {batch, num_directions, hidden_size}, {batch}, {num_directions, 4 * hidden_size, input_size}, {num_directions, 4 * hidden_size, hidden_size}, {num_directions, 4 * hidden_size}}, }; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/rnn_sequence.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/rnn_sequence.cpp index c8ffc311196..a87e79ed9dd 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/rnn_sequence.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/rnn_sequence.cpp @@ -10,7 +10,7 @@ namespace LayerTestsDefinitions { std::string RNNSequenceTest::getTestCaseName(const testing::TestParamInfo &obj) { ngraph::helpers::SequenceTestsMode mode; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size; @@ -21,7 +21,7 @@ namespace LayerTestsDefinitions { ngraph::op::RecurrentSequenceDirection direction; InferenceEngine::Precision netPrecision; std::string targetDevice; - std::tie(mode, seq_lenghts, batch, hidden_size, input_size, activations, clip, direction, netPrecision, + std::tie(mode, seq_lengths, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = obj.param; std::vector> inputShapes = { {{batch, input_size}, {batch, hidden_size}, {batch, hidden_size}, {hidden_size, input_size}, @@ -29,7 +29,7 @@ namespace LayerTestsDefinitions { }; std::ostringstream result; result << "mode=" << mode << "_"; - result << "seq_lenghts=" << seq_lenghts << "_"; + result << "seq_lengths=" << seq_lengths << "_"; result << "batch=" << batch << "_"; result << "hidden_size=" << hidden_size << "_"; result << "input_size=" << input_size << "_"; @@ -44,7 +44,7 @@ namespace LayerTestsDefinitions { void RNNSequenceTest::SetUp() { using namespace ngraph::helpers; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size; @@ -54,15 +54,15 @@ namespace LayerTestsDefinitions { float clip; ngraph::op::RecurrentSequenceDirection direction; InferenceEngine::Precision netPrecision; - std::tie(m_mode, seq_lenghts, batch, hidden_size, input_size, activations, clip, direction, netPrecision, + std::tie(m_mode, seq_lengths, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = this->GetParam(); size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; std::vector> inputShapes = { - {{batch, seq_lenghts, input_size}, {batch, num_directions, hidden_size}, {batch}, + {{batch, seq_lengths, input_size}, {batch, num_directions, hidden_size}, {batch}, {num_directions, hidden_size, input_size}, {num_directions, hidden_size, hidden_size}, {num_directions, hidden_size}}, }; - m_max_seq_len = seq_lenghts; + m_max_seq_len = seq_lengths; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]}); if (m_mode == SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM || diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/tensor_iterator.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/tensor_iterator.cpp index 6686c917e9d..ebbcd2753a8 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/tensor_iterator.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/tensor_iterator.cpp @@ -9,7 +9,7 @@ namespace LayerTestsDefinitions { std::string TensorIteratorTest::getTestCaseName(const testing::TestParamInfo &obj) { bool should_decompose; - size_t seq_lenghts; + size_t seq_lengths; size_t batch; size_t hidden_size; size_t input_size = 10; @@ -19,7 +19,7 @@ namespace LayerTestsDefinitions { ngraph::op::RecurrentSequenceDirection direction; InferenceEngine::Precision netPrecision; std::string targetDevice; - std::tie(should_decompose, seq_lenghts, batch, hidden_size, sequence_axis, clip, ti_body, direction, netPrecision, + std::tie(should_decompose, seq_lengths, batch, hidden_size, sequence_axis, clip, ti_body, direction, netPrecision, targetDevice) = obj.param; std::vector> inputShapes = {}; @@ -44,7 +44,7 @@ namespace LayerTestsDefinitions { std::ostringstream result; result << "unrolling=" << should_decompose << "_"; - result << "seq_len=" << seq_lenghts << "_"; + result << "seq_len=" << seq_lengths << "_"; result << "seq_len_axis=" << sequence_axis << "_"; result << "batch=" << batch << "_"; result << "hidden_size=" << hidden_size << "_"; @@ -59,7 +59,7 @@ namespace LayerTestsDefinitions { } void TensorIteratorTest::SetUp() { - size_t seq_lenghts; + size_t seq_lengths; bool should_decompose; size_t batch; size_t hidden_size; @@ -69,7 +69,7 @@ namespace LayerTestsDefinitions { float clip; ngraph::op::RecurrentSequenceDirection direction; InferenceEngine::Precision netPrecision; - std::tie(should_decompose, seq_lenghts, batch, hidden_size, sequence_axis, clip, ti_body, direction, netPrecision, + std::tie(should_decompose, seq_lengths, batch, hidden_size, sequence_axis, clip, ti_body, direction, netPrecision, targetDevice) = this->GetParam(); std::vector> inputShapes; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); @@ -84,7 +84,7 @@ namespace LayerTestsDefinitions { switch (ti_body) { case ngraph::helpers::TensorIteratorBody::LSTM: { inputShapes = { - {{batch, seq_lenghts, input_size}, {batch, hidden_size}, {batch, hidden_size}, {4 * hidden_size, input_size}, + {{batch, seq_lengths, input_size}, {batch, hidden_size}, {batch, hidden_size}, {4 * hidden_size, input_size}, {4 * hidden_size, hidden_size}, {4 * hidden_size}}, }; if (sequence_axis == 0) { @@ -130,7 +130,7 @@ namespace LayerTestsDefinitions { } case ngraph::helpers::TensorIteratorBody::GRU: { inputShapes = { - {{batch, seq_lenghts, input_size}, {batch, hidden_size}, {3 * hidden_size, input_size}, + {{batch, seq_lengths, input_size}, {batch, hidden_size}, {3 * hidden_size, input_size}, {3 * hidden_size, hidden_size}, {3 * hidden_size}}, }; if (sequence_axis == 0) { @@ -172,7 +172,7 @@ namespace LayerTestsDefinitions { break; } case ngraph::helpers::TensorIteratorBody::RNN: { - inputShapes = {{batch, seq_lenghts, input_size}, + inputShapes = {{batch, seq_lengths, input_size}, {batch, hidden_size}, {hidden_size, input_size}, {hidden_size, hidden_size}, diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/prepare_buffer_fusing.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/prepare_buffer_fusing.cpp index d3618d1034b..befc677b6f7 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/prepare_buffer_fusing.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/prepare_buffer_fusing.cpp @@ -209,7 +209,7 @@ void concat_in_place_optimization::optimize_cascade(concatenation_node& node, st // apply concatenation in place optimization for (auto input : node.get_dependencies()) { - auto input_lenght = input->get_output_layout().size.raw[concat_axis]; + auto input_length = input->get_output_layout().size.raw[concat_axis]; if (input->is_type() && input->can_be_optimized()) need_reoptimization.push_back(&input->as()); @@ -218,7 +218,7 @@ void concat_in_place_optimization::optimize_cascade(concatenation_node& node, st // // |--- lower padd ---| |---------- upper padd -----------| // |-- output padd ---| ----- input1 ------|----- input2 -----|-- out padd --| - upper_padd.raw[concat_axis] -= input_lenght; + upper_padd.raw[concat_axis] -= input_length; // set new padding for input input->set_output_padding(padding(lower_padd.sizes(), upper_padd.sizes())); @@ -227,7 +227,7 @@ void concat_in_place_optimization::optimize_cascade(concatenation_node& node, st // // |-------------- lower padd -------------|---------- upper padd -----------| // |-- output padd ---| ----- input1 ------|----- input2 -----|-- out padd --| - lower_padd.raw[concat_axis] += input_lenght; + lower_padd.raw[concat_axis] += input_length; } node.can_be_optimized(true); diff --git a/inference-engine/thirdparty/mkl-dnn b/inference-engine/thirdparty/mkl-dnn index d8514fcf88e..a5fffb52b01 160000 --- a/inference-engine/thirdparty/mkl-dnn +++ b/inference-engine/thirdparty/mkl-dnn @@ -1 +1 @@ -Subproject commit d8514fcf88e9770f671074ffe0ea853d734ebbcd +Subproject commit a5fffb52b012b31c65ace894638ecfb8948de9ec diff --git a/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_no_boot_tests.cpp b/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_no_boot_tests.cpp index 4293da658a8..fe8c522ac3c 100644 --- a/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_no_boot_tests.cpp +++ b/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_no_boot_tests.cpp @@ -31,20 +31,20 @@ TEST_F(MvncNoBootOpenDevice, OpenTwiceSameHandler) { deviceDesc.platform = NC_ANY_PLATFORM; char dev_addr_first_open[MAX_DEV_NAME]; - unsigned int data_lenght_first = MAX_DEV_NAME; + unsigned int data_length_first = MAX_DEV_NAME; char dev_addr_second_open[MAX_DEV_NAME]; - unsigned int data_lenght_second = MAX_DEV_NAME; + unsigned int data_length_second = MAX_DEV_NAME; // First open, get device name ASSERT_NO_ERROR(ncDeviceOpen(&deviceHandle, deviceDesc, watchdogInterval, firmwarePath)); ASSERT_NO_ERROR(ncDeviceGetOption(deviceHandle, NC_RO_DEVICE_NAME, - dev_addr_first_open, &data_lenght_first)); + dev_addr_first_open, &data_length_first)); // Second open, get device name ASSERT_NO_ERROR(ncDeviceOpen(&deviceHandle, deviceDesc, watchdogInterval, firmwarePath)); ASSERT_NO_ERROR(ncDeviceGetOption(deviceHandle, NC_RO_DEVICE_NAME, - dev_addr_second_open, &data_lenght_second)); + dev_addr_second_open, &data_length_second)); ASSERT_NO_ERROR(ncDeviceClose(&deviceHandle)); // Should be the same device diff --git a/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_tests_common.cpp b/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_tests_common.cpp index 02eda4c3dca..0f7b69d1b49 100644 --- a/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_tests_common.cpp +++ b/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_tests_common.cpp @@ -220,20 +220,20 @@ TEST_P(MvncOpenDevice, OpenTwiceSameHandler) { deviceDesc.platform = NC_ANY_PLATFORM; char dev_addr_first_open[MAX_DEV_NAME]; - unsigned int data_lenght_first = MAX_DEV_NAME; + unsigned int data_length_first = MAX_DEV_NAME; char dev_addr_second_open[MAX_DEV_NAME]; - unsigned int data_lenght_second = MAX_DEV_NAME; + unsigned int data_length_second = MAX_DEV_NAME; // First open, get device name ASSERT_NO_ERROR(ncDeviceOpen(&deviceHandle, deviceDesc, m_ncDeviceOpenParams)); ASSERT_NO_ERROR(ncDeviceGetOption(deviceHandle, NC_RO_DEVICE_NAME, - dev_addr_first_open, &data_lenght_first)); + dev_addr_first_open, &data_length_first)); // Second open, get device name ASSERT_NO_ERROR(ncDeviceOpen(&deviceHandle, deviceDesc, m_ncDeviceOpenParams)); ASSERT_NO_ERROR(ncDeviceGetOption(deviceHandle, NC_RO_DEVICE_NAME, - dev_addr_second_open, &data_lenght_second)); + dev_addr_second_open, &data_length_second)); ASSERT_NO_ERROR(ncDeviceClose(&deviceHandle, m_watchdogHndl)); // Should be the same device diff --git a/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_tests_usb.cpp b/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_tests_usb.cpp index 65a2a09fb23..87544a6e0c6 100644 --- a/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_tests_usb.cpp +++ b/inference-engine/thirdparty/movidius/mvnc/tests/mvnc_tests_usb.cpp @@ -113,7 +113,7 @@ TEST_F(MvncOpenUSBDevice, OpenAvailableDeviceByName) { GTEST_SKIP(); char dev_addr_open[NC_MAX_NAME_SIZE]; - unsigned int data_lenght = NC_MAX_NAME_SIZE; + unsigned int data_length = NC_MAX_NAME_SIZE; auto availableDevices = getDevicesList(); @@ -122,7 +122,7 @@ TEST_F(MvncOpenUSBDevice, OpenAvailableDeviceByName) { ASSERT_NO_ERROR(ncDeviceOpen(&deviceHandle_, deviceDesc_, m_ncDeviceOpenParams)); ASSERT_NO_ERROR(ncDeviceGetOption(deviceHandle_, NC_RO_DEVICE_NAME, - dev_addr_open, &data_lenght)); + dev_addr_open, &data_length)); ASSERT_TRUE(strncmp(dev_addr_open, deviceDesc_.name, NC_MAX_NAME_SIZE) == 0); ASSERT_NO_ERROR(ncDeviceClose(&deviceHandle_, m_watchdogHndl)); @@ -147,10 +147,10 @@ TEST_F(MvncOpenUSBDevice, OpenTwiceSameHandlerByName) { GTEST_SKIP(); char dev_addr_first_open[MAX_DEV_NAME]; - unsigned int data_lenght_first = MAX_DEV_NAME; + unsigned int data_length_first = MAX_DEV_NAME; char dev_addr_second_open[MAX_DEV_NAME]; - unsigned int data_lenght_second = MAX_DEV_NAME; + unsigned int data_length_second = MAX_DEV_NAME; auto availableDevices = getDevicesList(); @@ -159,12 +159,12 @@ TEST_F(MvncOpenUSBDevice, OpenTwiceSameHandlerByName) { ASSERT_NO_ERROR(ncDeviceOpen(&deviceHandle_, deviceDesc_, m_ncDeviceOpenParams)); ASSERT_NO_ERROR(ncDeviceGetOption(deviceHandle_, NC_RO_DEVICE_NAME, - dev_addr_first_open, &data_lenght_first)); + dev_addr_first_open, &data_length_first)); // Second open, get device name ASSERT_NO_ERROR(ncDeviceOpen(&deviceHandle_, deviceDesc_, m_ncDeviceOpenParams)); ASSERT_NO_ERROR(ncDeviceGetOption(deviceHandle_, NC_RO_DEVICE_NAME, - dev_addr_second_open, &data_lenght_second)); + dev_addr_second_open, &data_length_second)); ASSERT_NO_ERROR(ncDeviceClose(&deviceHandle_, m_watchdogHndl)); // Should be the same device diff --git a/inference-engine/thirdparty/pugixml/src/pugixml.cpp b/inference-engine/thirdparty/pugixml/src/pugixml.cpp index 69eba5e1277..e6c409bc0f5 100644 --- a/inference-engine/thirdparty/pugixml/src/pugixml.cpp +++ b/inference-engine/thirdparty/pugixml/src/pugixml.cpp @@ -3953,9 +3953,9 @@ PUGI__NS_BEGIN // skip ]] if we stopped at ]]>, > will go to the next CDATA section if (*s) s += 2; - size_t bufLenght = static_cast(s - prev); + size_t bufLength = static_cast(s - prev); - writer.write_buffer(prev, bufLenght); + writer.write_buffer(prev, bufLength); writer.write(']', ']', '>'); } @@ -4013,9 +4013,9 @@ PUGI__NS_BEGIN // look for -\0 or -- sequence - we can't output it since -- is illegal in comment body while (*s && !(s[0] == '-' && (s[1] == '-' || s[1] == 0))) ++s; - size_t bufLenght = static_cast(s - prev); + size_t bufLength = static_cast(s - prev); - writer.write_buffer(prev, bufLenght); + writer.write_buffer(prev, bufLength); if (*s) { diff --git a/ngraph/core/include/ngraph/op/ctc_loss.hpp b/ngraph/core/include/ngraph/op/ctc_loss.hpp index 23f8e4ff570..b5e364877af 100644 --- a/ngraph/core/include/ngraph/op/ctc_loss.hpp +++ b/ngraph/core/include/ngraph/op/ctc_loss.hpp @@ -21,7 +21,7 @@ namespace ngraph /// \brief Constructs a CTCLoss operation /// /// \param logits 3-D tensor of logits - /// \param logit_length 1-D tensor of lenght for each object from + /// \param logit_length 1-D tensor of length for each object from /// a batch /// \param labels 2-D tensor of labels for which likelyhood /// is estimated using logist diff --git a/ngraph/core/include/ngraph/op/lstm_sequence.hpp b/ngraph/core/include/ngraph/op/lstm_sequence.hpp index b5c0ec5dfef..eb0692efcd0 100644 --- a/ngraph/core/include/ngraph/op/lstm_sequence.hpp +++ b/ngraph/core/include/ngraph/op/lstm_sequence.hpp @@ -98,13 +98,13 @@ namespace ngraph private: /// - /// \brief Gets the masked value according to sequence lenght in a batch. + /// \brief Gets the masked value according to sequence length in a batch. /// /// \note Zeros out values or sets them to default value for inputs with - /// sequence lenght shorter than currently procssed time step. + /// sequence length shorter than currently procssed time step. /// /// \param[in] data The input value. - /// \param[in] time_step The current time step denoting sequence lenght. + /// \param[in] time_step The current time step denoting sequence length. /// \param[in] batch_axis The batch axis index of data tensor. /// \param[in] default_value The default value for masked elements. /// diff --git a/ngraph/frontend/onnx_import/src/op/slice.cpp b/ngraph/frontend/onnx_import/src/op/slice.cpp index 2b9f5f0b520..26010a5bda0 100644 --- a/ngraph/frontend/onnx_import/src/op/slice.cpp +++ b/ngraph/frontend/onnx_import/src/op/slice.cpp @@ -54,7 +54,7 @@ namespace ngraph /// value) or ignored (1 value) /// /// \param[in] axes Axes input of ONNX Slice operator - /// \param[in] slice_indices_length Lenght of Slice indices + /// \param[in] slice_indices_length Length of Slice indices /// (starts, ends, steps) /// /// \return Mask attribute in format required by StridedSlice:v1 diff --git a/ngraph/frontend/onnx_import/src/utils/tensor_external_data.cpp b/ngraph/frontend/onnx_import/src/utils/tensor_external_data.cpp index 77b6db14beb..fe593b47619 100644 --- a/ngraph/frontend/onnx_import/src/utils/tensor_external_data.cpp +++ b/ngraph/frontend/onnx_import/src/utils/tensor_external_data.cpp @@ -25,7 +25,7 @@ namespace ngraph if (entry.key() == "offset") m_offset = std::stoi(entry.value()); if (entry.key() == "length") - m_data_lenght = std::stoi(entry.value()); + m_data_length = std::stoi(entry.value()); if (entry.key() == "checksum") m_sha1_digest = std::stoi(entry.value()); } @@ -43,11 +43,11 @@ namespace ngraph if (external_data_stream.fail()) throw error::invalid_external_data{*this}; - std::streamsize read_data_lenght; - if (m_data_lenght == 0) // read entire file - read_data_lenght = external_data_stream.tellg(); + std::streamsize read_data_length; + if (m_data_length == 0) // read entire file + read_data_length = external_data_stream.tellg(); else - read_data_lenght = m_data_lenght; + read_data_length = m_data_length; const auto page_size = 4096; if (m_offset != 0 && m_offset % page_size != 0) @@ -65,8 +65,8 @@ namespace ngraph } std::string read_data; - read_data.resize(read_data_lenght); - external_data_stream.read(&read_data[0], read_data_lenght); + read_data.resize(read_data_length); + external_data_stream.read(&read_data[0], read_data_length); external_data_stream.close(); return read_data; @@ -78,7 +78,7 @@ namespace ngraph s << "ExternalDataInfo("; s << "data_full_path: " << m_data_location; s << ", offset: " << m_offset; - s << ", data_lenght: " << m_data_lenght; + s << ", data_length: " << m_data_length; s << ", sha1_digest: " << m_sha1_digest << ")"; return s.str(); } diff --git a/ngraph/frontend/onnx_import/src/utils/tensor_external_data.hpp b/ngraph/frontend/onnx_import/src/utils/tensor_external_data.hpp index 6db383428ea..8af53e407c1 100644 --- a/ngraph/frontend/onnx_import/src/utils/tensor_external_data.hpp +++ b/ngraph/frontend/onnx_import/src/utils/tensor_external_data.hpp @@ -35,7 +35,7 @@ namespace ngraph private: std::string m_data_location{}; int m_offset = 0; - int m_data_lenght = 0; + int m_data_length = 0; int m_sha1_digest = 0; }; } // namespace detail diff --git a/ngraph/python/tests/test_ngraph/test_data_movement.py b/ngraph/python/tests/test_ngraph/test_data_movement.py index aa1c41dbfd9..f9693147e97 100644 --- a/ngraph/python/tests/test_ngraph/test_data_movement.py +++ b/ngraph/python/tests/test_ngraph/test_data_movement.py @@ -63,17 +63,17 @@ def test_reverse_sequence(): ], dtype=np.int32, ).reshape([2, 3, 4, 2]) - seq_lenghts = np.array([1, 2, 1, 2], dtype=np.int32) + seq_lengths = np.array([1, 2, 1, 2], dtype=np.int32) batch_axis = 2 sequence_axis = 1 input_param = ng.parameter(input_data.shape, name="input", dtype=np.int32) - seq_lengths_param = ng.parameter(seq_lenghts.shape, name="sequence lengths", dtype=np.int32) + seq_lengths_param = ng.parameter(seq_lengths.shape, name="sequence lengths", dtype=np.int32) model = ng.reverse_sequence(input_param, seq_lengths_param, batch_axis, sequence_axis) runtime = get_runtime() computation = runtime.computation(model, input_param, seq_lengths_param) - result = computation(input_data, seq_lenghts) + result = computation(input_data, seq_lengths) expected = np.array( [ diff --git a/ngraph/test/backend/reverse_sequence.in.cpp b/ngraph/test/backend/reverse_sequence.in.cpp index 4dcc954e4c0..bab37dfa5a6 100644 --- a/ngraph/test/backend/reverse_sequence.in.cpp +++ b/ngraph/test/backend/reverse_sequence.in.cpp @@ -44,8 +44,8 @@ NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n2c3h4w2) 12, 0, 15, 0, 18, 0, 21, 0, 13, 0, 16, 0, 19, 0, 22, 0, 14, 0, 17, 0, 20, 0, 23, 0, }; - std::vector seq_lenghts{1, 2, 1, 2}; - copy_data(b, seq_lenghts); + std::vector seq_lengths{1, 2, 1, 2}; + copy_data(b, seq_lengths); std::vector expected{ 0, 0, 4, 0, 6, 0, 10, 0, 1, 0, 3, 0, 7, 0, 9, 0, 2, 0, 5, 0, 8, 0, 11, 0, @@ -81,8 +81,8 @@ NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n4c3h2w2) shared_ptr result = backend->create_tensor(element::i32, shape); - std::vector seq_lenghts{1, 2, 3, 3}; - copy_data(b, seq_lenghts); + std::vector seq_lengths{1, 2, 3, 3}; + copy_data(b, seq_lengths); std::vector input{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, @@ -137,8 +137,8 @@ NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n4d2c3h2w2) copy_data(a, input); - std::vector seq_lenghts{1, 2, 1, 2}; - copy_data(b, seq_lenghts); + std::vector seq_lengths{1, 2, 1, 2}; + copy_data(b, seq_lengths); auto handle = backend->compile(f); handle->call_with_validate({result}, {a, b}); @@ -171,8 +171,8 @@ NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_negative_axes) 12, 0, 15, 0, 18, 0, 21, 0, 13, 0, 16, 0, 19, 0, 22, 0, 14, 0, 17, 0, 20, 0, 23, 0, }; - std::vector seq_lenghts{1, 2, 1, 2}; - copy_data(b, seq_lenghts); + std::vector seq_lengths{1, 2, 1, 2}; + copy_data(b, seq_lengths); std::vector expected{ 0, 0, 4, 0, 6, 0, 10, 0, 1, 0, 3, 0, 7, 0, 9, 0, 2, 0, 5, 0, 8, 0, 11, 0, diff --git a/ngraph/test/onnx/onnx_import_external_data.in.cpp b/ngraph/test/onnx/onnx_import_external_data.in.cpp index 6d318ca0436..10638eaa200 100644 --- a/ngraph/test/onnx/onnx_import_external_data.in.cpp +++ b/ngraph/test/onnx/onnx_import_external_data.in.cpp @@ -101,7 +101,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_external_invalid_external_data_exception) { EXPECT_PRED_FORMAT2( testing::IsSubstring, - std::string("not_existed_file.data, offset: 4096, data_lenght: 16, sha1_digest: 0)"), + std::string("not_existed_file.data, offset: 4096, data_length: 16, sha1_digest: 0)"), error.what()); } catch (...) @@ -123,7 +123,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_external_invalid_up_dir_path) { EXPECT_PRED_FORMAT2(testing::IsSubstring, std::string("tensor.data, offset: 4096, " - "data_lenght: 16, sha1_digest: 0)"), + "data_length: 16, sha1_digest: 0)"), error.what()); } catch (...) diff --git a/ngraph/test/type_prop/reverse_sequence.cpp b/ngraph/test/type_prop/reverse_sequence.cpp index 38be9f2aec4..fa1b57bea45 100644 --- a/ngraph/test/type_prop/reverse_sequence.cpp +++ b/ngraph/test/type_prop/reverse_sequence.cpp @@ -12,13 +12,13 @@ using namespace ngraph; TEST(type_prop, reverse_sequence_1_dim) { auto data = make_shared(element::f32, Shape{4, 3, 2}); - auto seq_lenghts = make_shared(element::f32, Shape{4, 4}); + auto seq_lengths = make_shared(element::f32, Shape{4, 4}); try { size_t batch_axis = 0; size_t seq_axis = 1; - auto bc = make_shared(data, seq_lenghts, batch_axis, seq_axis); - FAIL() << "ReverseSequence c-tor should throw for seq_lenghts whose rank isn't equal to 1"; + auto bc = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "ReverseSequence c-tor should throw for seq_lengths whose rank isn't equal to 1"; } catch (const NodeValidationFailure& error) { @@ -34,12 +34,12 @@ TEST(type_prop, reverse_sequence_1_dim) TEST(type_prop, reverse_sequence_batch_index_oob) { auto data = make_shared(element::f32, Shape{4, 3, 2}); - auto seq_lenghts = make_shared(element::f32, Shape{3}); + auto seq_lengths = make_shared(element::f32, Shape{3}); try { size_t batch_axis = 3; size_t seq_axis = 1; - auto bc = make_shared(data, seq_lenghts, batch_axis, seq_axis); + auto bc = make_shared(data, seq_lengths, batch_axis, seq_axis); FAIL() << "ReverseSequence c-tor should throw for out-of-bounds batch axis index"; } catch (const ngraph_error& error) @@ -76,12 +76,12 @@ TEST(type_prop, reverse_sequence_sequence_index_oob) TEST(type_prop, reverse_sequence_seq_len_size_equal_to_batch_dim) { auto data = make_shared(element::f32, Shape{4, 3, 2}); - auto seq_lenghts = make_shared(element::f32, Shape{3}); + auto seq_lengths = make_shared(element::f32, Shape{3}); try { size_t batch_axis = 0; size_t seq_axis = 1; - auto bc = make_shared(data, seq_lenghts, batch_axis, seq_axis); + auto bc = make_shared(data, seq_lengths, batch_axis, seq_axis); FAIL() << "ReverseSequence c-tor should throw when sequence length size isn't equal to " "batch dimension"; } From c1b1e2e7afc698ac82b32bb1f502ad2e90cd1419 Mon Sep 17 00:00:00 2001 From: Vladimir Paramuzov Date: Thu, 13 May 2021 09:17:32 +0300 Subject: [PATCH 46/99] [IE CLDNN] Fixed FC weights check (#5568) --- inference-engine/src/cldnn_engine/ops/matmul.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/inference-engine/src/cldnn_engine/ops/matmul.cpp b/inference-engine/src/cldnn_engine/ops/matmul.cpp index 289a5cb5d7d..b18e199581c 100644 --- a/inference-engine/src/cldnn_engine/ops/matmul.cpp +++ b/inference-engine/src/cldnn_engine/ops/matmul.cpp @@ -60,8 +60,7 @@ void CreateMatMulOp(Program& p, const std::shared_ptr& o auto shape_a = op->get_input_shape(0); auto shape_b = op->get_input_shape(1); - bool is_fc = ngraph::is_type(op->get_input_node_shared_ptr(1)) || - ngraph::is_type(op->get_input_node_shared_ptr(1)); + bool is_fc = IsNodeOnConstPath(op->get_input_node_shared_ptr(1)); is_fc &= std::count_if(shape_b.begin(), shape_b.end(), [](size_t x) { return x != 1; }) <= 2; if (is_fc) { From 5c4061324724005163e6ad67abf7343a0637e09a Mon Sep 17 00:00:00 2001 From: Tatiana Troilova Date: Thu, 13 May 2021 13:30:20 +0300 Subject: [PATCH 47/99] updated third-party-programs.txt (#5607) --- licensing/third-party-programs.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/licensing/third-party-programs.txt b/licensing/third-party-programs.txt index d59f1aaa5d9..03ddc3e168b 100644 --- a/licensing/third-party-programs.txt +++ b/licensing/third-party-programs.txt @@ -543,6 +543,30 @@ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABI ------------------------------------------------------------- +14. Deformable Convolutional Networks + +Copyright (c) 2017 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------------------------------------------------- + The following third party programs have their own third party program files. These additional third party program files are as follows: oneAPI Deep Neural Network Library (oneDNN) Third Party Programs File is available here https://github.com/openvinotoolkit/openvino/blob/master/licensing/onednn_third-party-programs.txt From 516479ae201cb95b1ab73373e03d887c5e13a635 Mon Sep 17 00:00:00 2001 From: Chenhu Wang Date: Thu, 13 May 2021 18:43:42 +0800 Subject: [PATCH 48/99] [CPU]shuffle_channel optimization (#4978) --- .../src/mkldnn_plugin/mkldnn_node.cpp | 4 +- .../src/mkldnn_plugin/mkldnn_node.h | 3 + .../src/mkldnn_plugin/mkldnn_plugin.cpp | 2 + .../nodes/common/permute_kernel.cpp | 14 +- .../nodes/common/permute_kernel.h | 1 + .../src/mkldnn_plugin/nodes/list_tbl.hpp | 1 - .../nodes/mkldnn_shuffle_channels_node.cpp | 247 ++++++++++++++++++ .../nodes/mkldnn_shuffle_channels_node.h | 40 +++ .../mkldnn_plugin/nodes/shuffle_channels.cpp | 201 -------------- .../single_layer_tests/shuffle_channels.cpp | 28 +- .../single_layer_tests/shuffle_channels.cpp | 222 ++++++++++++++++ 11 files changed, 534 insertions(+), 229 deletions(-) create mode 100644 inference-engine/src/mkldnn_plugin/nodes/mkldnn_shuffle_channels_node.cpp create mode 100644 inference-engine/src/mkldnn_plugin/nodes/mkldnn_shuffle_channels_node.h delete mode 100644 inference-engine/src/mkldnn_plugin/nodes/shuffle_channels.cpp create mode 100644 inference-engine/tests/functional/plugin/cpu/single_layer_tests/shuffle_channels.cpp diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_node.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_node.cpp index ca4db7fd47c..1692c411dfe 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_node.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_node.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -174,7 +175,8 @@ static const InferenceEngine::details::caseless_unordered_map { "GatherND", GatherND}, { "OneHot", OneHot}, { "RegionYolo", RegionYolo}, - { "Select", Select} + { "Select", Select}, + { "ShuffleChannels", ShuffleChannels}, }; Type TypeFromName(const std::string type) { diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_node.h b/inference-engine/src/mkldnn_plugin/mkldnn_node.h index 2a0102cccde..a592f785541 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_node.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_node.h @@ -91,6 +91,7 @@ enum Type { Select, Roll, Reference, + ShuffleChannels, }; Type TypeFromName(const std::string type); @@ -203,6 +204,8 @@ static std::string NameFromType(Type type) { return "Select"; case Roll: return "Roll"; + case ShuffleChannels: + return "ShuffleChannels"; default: return "Unknown"; } diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index 6b1ccc16282..a597a1233e4 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,7 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { pass_config->disable(); pass_config->disable(); pass_config->disable(); + pass_config->disable(); pass_config->disable(); pass_config->disable(); diff --git a/inference-engine/src/mkldnn_plugin/nodes/common/permute_kernel.cpp b/inference-engine/src/mkldnn_plugin/nodes/common/permute_kernel.cpp index 50e21be668f..4babccb5186 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/common/permute_kernel.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/common/permute_kernel.cpp @@ -134,8 +134,8 @@ private: Xbyak::Reg64 reg_params = abi_param1; - Vmm vmm = Vmm(0); - Xbyak::Xmm xmm = Xbyak::Xmm(0); + Vmm vmm = Vmm(1); + Xbyak::Xmm xmm = Xbyak::Xmm(1); }; PermuteKernel::PermuteKernel(const PermuteParams& params) : params(params) { @@ -275,6 +275,16 @@ void PermuteKernel::execute(const uint8_t* src_data, uint8_t* dst_data, const in referenceExecute(src_data, dst_data, mb); } +void PermuteKernel::execute(const uint8_t* src_data, uint8_t* dst_data) { + SizeVector dst_dims = jcp.dst_block_dims; + if (permute_kernel) { + optimizedExecute(src_data, dst_data, dst_dims[0]); + return; + } + + referenceExecute(src_data, dst_data, dst_dims[0]); +} + void PermuteKernel::optimizedExecute(const uint8_t* src_data, uint8_t* dst_data, const int mb) { SizeVector dst_dims = jcp.dst_block_dims; const SizeVector dst_strides = jcp.dst_strides; diff --git a/inference-engine/src/mkldnn_plugin/nodes/common/permute_kernel.h b/inference-engine/src/mkldnn_plugin/nodes/common/permute_kernel.h index be6427c7007..63497f3fa91 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/common/permute_kernel.h +++ b/inference-engine/src/mkldnn_plugin/nodes/common/permute_kernel.h @@ -55,6 +55,7 @@ class PermuteKernel { public: PermuteKernel(const PermuteParams& params); + void execute(const uint8_t* src_data, uint8_t* dst_data); void execute(const uint8_t* src_data, uint8_t* dst_data, const int mb); private: diff --git a/inference-engine/src/mkldnn_plugin/nodes/list_tbl.hpp b/inference-engine/src/mkldnn_plugin/nodes/list_tbl.hpp index de8fd66b708..669aeffa802 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/list_tbl.hpp +++ b/inference-engine/src/mkldnn_plugin/nodes/list_tbl.hpp @@ -41,7 +41,6 @@ MKLDNN_EXTENSION_NODE(ExperimentalDetectronROIFeatureExtractorImpl, Experimental MKLDNN_EXTENSION_NODE(ExperimentalDetectronGenerateProposalsSingleImageImpl, ExperimentalDetectronGenerateProposalsSingleImage); MKLDNN_EXTENSION_NODE(NonMaxSuppressionImpl, NonMaxSuppressionIEInternal); MKLDNN_EXTENSION_NODE(TopKImpl, TopK); -MKLDNN_EXTENSION_NODE(ShuffleChannelsImpl, ShuffleChannels); MKLDNN_EXTENSION_NODE(ExperimentalDetectronPriorGridGeneratorImpl, ExperimentalDetectronPriorGridGenerator); MKLDNN_EXTENSION_NODE(GRNImpl, GRN); MKLDNN_EXTENSION_NODE(BucketizeImpl, Bucketize); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_shuffle_channels_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_shuffle_channels_node.cpp new file mode 100644 index 00000000000..10d59bf0977 --- /dev/null +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_shuffle_channels_node.cpp @@ -0,0 +1,247 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "mkldnn_shuffle_channels_node.h" + +#include +#include +#include +#include "common/tensor_desc_creator.h" + +#include "common/cpu_memcpy.h" +#include "utils/general_utils.h" + +#include +#include + +#define THROW_SHCH_ERROR IE_THROW() << "ShuffleChannels layer with name '" << getName() << "' " + +using namespace mkldnn; +using namespace MKLDNNPlugin; +using namespace InferenceEngine; +using namespace mkldnn::impl; +using namespace mkldnn::impl::cpu::x64; + +bool MKLDNNShuffleChannelsNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { + try { + const auto shuffleChannels = std::dynamic_pointer_cast(op); + if (!shuffleChannels) { + errorMessage = "Only opset1 ShuffleChannels operation is supported"; + return false; + } + auto shapeSC = shuffleChannels->get_input_shape(0); + auto rankSC = shapeSC.size(); + auto axisSC = shuffleChannels->get_axis(); + auto groupSC = shuffleChannels->get_group(); + if (axisSC < 0) + axisSC += rankSC; + + if (axisSC < 0 || axisSC >= rankSC) { + errorMessage = "gets incorrect axis number, which should be in range of [-inputRank, inputRank)."; + return false; + } + + if (groupSC == 0 || shapeSC[axisSC] % groupSC) { + errorMessage = "gets incorrect group parameter('group' must evenly divide the channel dimension)."; + return false; + } + } catch (...) { + return false; + } + return true; +} + +MKLDNNShuffleChannelsNode::MKLDNNShuffleChannelsNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache) + : MKLDNNNode(op, eng, cache), permuteKernel_(nullptr), supportDynamicBatch_(false) { + std::string errorMessage; + if (!isSupportedOperation(op, errorMessage)) { + IE_THROW(NotImplemented) << errorMessage; + } + + const auto shuffleChannels = std::dynamic_pointer_cast(op); + inShape_ = shuffleChannels->get_input_shape(0); + dataRank_ = inShape_.size(); + axis_ = shuffleChannels->get_axis(); + if (axis_ < 0) + axis_ += dataRank_; + group_ = shuffleChannels->get_group(); + groupSize_ = inShape_[axis_] / group_; + + supportDynamicBatch_ = (axis_ != 0); +} + +void MKLDNNShuffleChannelsNode::getSupportedDescriptors() { +} + +void MKLDNNShuffleChannelsNode::initSupportedPrimitiveDescriptors() { + if (!supportedPrimitiveDescriptors.empty()) + return; + + InferenceEngine::Precision precision = getOriginalInputPrecisionAtPort(0); + const std::set supported_precision_sizes = {1, 2, 4, 8, 16}; + if (supported_precision_sizes.find(precision.size()) == supported_precision_sizes.end()) + THROW_SHCH_ERROR << "has unsupported precision: " << precision.name(); + + impl_desc_type impl_type; + if (mayiuse(cpu::x64::avx512_common)) { + impl_type = impl_desc_type::jit_avx512; + } else if (mayiuse(cpu::x64::avx2)) { + impl_type = impl_desc_type::jit_avx2; + } else if (mayiuse(cpu::x64::sse41)) { + impl_type = impl_desc_type::jit_sse42; + } else { + impl_type = impl_desc_type::ref; + } + + addSupportedPrimDesc({{TensorDescCreatorTypes::nspc, precision}}, + {{TensorDescCreatorTypes::nspc, precision}}, + impl_type, supportDynamicBatch_); + addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, precision}}, + {{TensorDescCreatorTypes::ncsp, precision}}, + impl_type, supportDynamicBatch_); + // canUseBlocked + if (axis_ != 1) { + addSupportedPrimDesc({{TensorDescCreatorTypes::nCsp8c, precision}}, + {{TensorDescCreatorTypes::nCsp8c, precision}}, + impl_type, supportDynamicBatch_); + addSupportedPrimDesc({{TensorDescCreatorTypes::nCsp16c, precision}}, + {{TensorDescCreatorTypes::nCsp16c, precision}}, + impl_type, supportDynamicBatch_); + } +} + +void MKLDNNShuffleChannelsNode::createPrimitive() { + if (prim) + return; + auto &dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); + auto &srcMemPtr = getParentEdgeAt(0)->getMemoryPtr(); + if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr()) + THROW_SHCH_ERROR << "has not allocated destination memory"; + if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) + THROW_SHCH_ERROR << "has not allocated input memory"; + if (getSelectedPrimitiveDescriptor() == nullptr) + THROW_SHCH_ERROR << "has unidentified preferable primitive descriptor"; + + const bool isBlocked = getParentEdgeAt(0)->getMemory().GetDesc().isBlockedCFormat(); + + int batchRank = axis_; + int spatialRank = dataRank_ - axis_ - 1; + + // 2 for decomposed axis dim, 1 for composed spatial dim + int reshapedRank = batchRank + 2 + static_cast(spatialRank != 0) + static_cast(isBlocked && (spatialRank == 0)); + PermuteParams params; + params.data_size = getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc.getPrecision().size(); + params.order.resize(reshapedRank, 0); + params.src_block_order.resize(reshapedRank); + params.dst_block_order.resize(reshapedRank); + params.dst_block_dims.resize(reshapedRank); + params.src_block_dims.resize(reshapedRank); + + size_t spatialShapeSize = 1; + if (spatialRank != 0) { + for (int i = batchRank + 1; i < dataRank_; i++) { + spatialShapeSize *= inShape_[i]; + } + } + + auto decomposeAndTranpose = [&](int axis) { + params.src_block_dims[axis] = group_; + params.src_block_dims[axis + 1] = groupSize_; + params.order[axis] = axis + 1; + params.order[axis + 1] = axis; + }; + + const int channelDim = 1; + if (isBlocked) { + size_t blkSize = getParentEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims().back(); + size_t CB = div_up(inShape_[1], blkSize); + SizeVector srcBlockedDims = getParentEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims(); + if (axis_ > channelDim) { // axis on spatial + for (int i = 0; i < batchRank; i++) { + params.order[i] = i; + params.src_block_dims[i] = srcBlockedDims[i]; + } + decomposeAndTranpose(batchRank); + + params.order[batchRank + 2] = batchRank + 2; + params.src_block_dims[batchRank + 2] = spatialShapeSize * blkSize; + } else { // axis on batch + decomposeAndTranpose(0); + size_t spatialShapeSize = CB * blkSize; + for (int i = 2; i < dataRank_; i++) { + spatialShapeSize *= inShape_[i]; + } + params.order[2] = 2; + params.src_block_dims[2] = spatialShapeSize; + } + } else if (getParentEdgeAt(0)->getMemory().GetDesc().isTailCFormat()) { + if (axis_ == channelDim) { // axis on channel + params.order[0] = 0; + params.src_block_dims[0] = inShape_[0]; + params.order[1] = 1; + params.src_block_dims[1] = spatialShapeSize; + decomposeAndTranpose(2); + } else if (axis_ > channelDim) { // axis on spatial + for (int i = 0; i < batchRank; i++) { + if (i == 0) { + params.order[i] = i; + params.src_block_dims[i] = inShape_[i]; + } else if (i == 1) { + params.order[reshapedRank - 1] = reshapedRank - 1; + params.src_block_dims[params.order[reshapedRank - 1]] = inShape_[i]; + } else if (i > 1) { + params.order[i - 1] = i - 1; + params.src_block_dims[i - 1] = inShape_[i]; + } + } + decomposeAndTranpose(batchRank - 1); + + if (spatialRank != 0) { + params.order[batchRank + 1] = batchRank + 1; + params.src_block_dims[batchRank + 1] = spatialShapeSize; + } + } else { // axis on batch + decomposeAndTranpose(0); + params.order[2] = 2; + params.src_block_dims[2] = spatialShapeSize; + } + } else { + for (int i = 0; i < batchRank; i++) { + params.src_block_dims[i] = inShape_[i]; + params.order[i] = i; + } + + decomposeAndTranpose(batchRank); + if (spatialRank != 0) { + params.order[batchRank + 2] = batchRank + 2; + params.src_block_dims[batchRank + 2] = spatialShapeSize; + } + } + + std::iota(params.src_block_order.begin(), params.src_block_order.end(), 0); + std::iota(params.dst_block_order.begin(), params.dst_block_order.end(), 0); + for (size_t i = 0; i < reshapedRank; i++) + params.dst_block_dims[i] = params.src_block_dims[params.order[i]]; + + permuteKernel_ = std::unique_ptr(new PermuteKernel(params)); +} + +void MKLDNNShuffleChannelsNode::execute(mkldnn::stream strm) { + auto srcData = reinterpret_cast(this->getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); + auto dstData = reinterpret_cast(this->getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); + if (permuteKernel_) { + if (supportDynamicBatch_) + permuteKernel_->execute(srcData, dstData, batchToProcess()); + else + permuteKernel_->execute(srcData, dstData); + } else { + THROW_SHCH_ERROR << "does not initialize permute kernel to execute."; + } +} + +bool MKLDNNShuffleChannelsNode::created() const { + return getType() == ShuffleChannels; +} + +REG_MKLDNN_PRIM_FOR(MKLDNNShuffleChannelsNode, ShuffleChannels); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_shuffle_channels_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_shuffle_channels_node.h new file mode 100644 index 00000000000..7206b1ae363 --- /dev/null +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_shuffle_channels_node.h @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include +#include "common/permute_kernel.h" + +namespace MKLDNNPlugin { + +class MKLDNNShuffleChannelsNode : public MKLDNNNode { +public: + MKLDNNShuffleChannelsNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); + ~MKLDNNShuffleChannelsNode() override = default; + + void getSupportedDescriptors() override; + void initSupportedPrimitiveDescriptors() override; + void createPrimitive() override; + void execute(mkldnn::stream strm) override; + bool created() const override; + + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; + +private: + ngraph::Shape inShape_; + int dataRank_; + int axis_; + size_t group_; + size_t groupSize_; + + std::unique_ptr permuteKernel_; + bool supportDynamicBatch_; +}; + +} // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/shuffle_channels.cpp b/inference-engine/src/mkldnn_plugin/nodes/shuffle_channels.cpp deleted file mode 100644 index bec57b38a39..00000000000 --- a/inference-engine/src/mkldnn_plugin/nodes/shuffle_channels.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "base.hpp" - -#include -#include -#include -#include -#include -#include "ie_parallel.hpp" -#include "common/cpu_memcpy.h" -#include -#include "common/tensor_desc_creator.h" - -namespace InferenceEngine { -namespace Extensions { -namespace Cpu { - -using MKLDNNPlugin::TensorDescCreatorTypes; - -class ShuffleChannelsImpl: public ExtLayerBase { -#define CNTR_SIZE 3 - -__inline size_t initter(size_t start, size_t size, size_t* counters, size_t* own_dims, size_t* ownStrides) { - size_t i = start; - size_t idx = 0; - for (int j = size - 1; j >= 0; j--) { - counters[j] = i % own_dims[j]; - idx += counters[j] * ownStrides[j]; - i /= own_dims[j]; - } - return idx; -} - -__inline size_t updater(size_t idx, size_t size, size_t* counters, size_t* own_dims, size_t* ownStrides) { - size_t i = 1; - for (int j = size - 1; j >= 0; j--) { - counters[j]++; - if (counters[j] < own_dims[j]) { - idx += ownStrides[j]; - break; - } else { - counters[j] = 0; - i = 0; - } - } - if (!i) { - for (idx = 0; i < CNTR_SIZE; ++i) - idx += counters[i] * ownStrides[i]; - } - return idx; -} - -public: - bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { - try { - auto scOp = ngraph::as_type_ptr(op); - if (!scOp) { - errorMessage = "Node is not an instance of the TopK from the operations set v1."; - return false; - } - - if (_supported_precisions_sizes.find(op->get_input_element_type(0).size()) == _supported_precisions_sizes.end()) { - errorMessage = "Unsupported precision: " + op->get_input_element_type(0).get_type_name(); - return false; - } - } catch (...) { - return false; - } - return true; - } - - explicit ShuffleChannelsImpl(const std::shared_ptr& op) { - try { - std::string errorMessage; - if (!isSupportedOperation(op, errorMessage)) { - IE_THROW(NotImplemented) << errorMessage; - } - auto scOp = ngraph::as_type_ptr(op); - auto& dstDims = op->get_output_shape(0); - - int64_t axis = scOp->get_axis(); - if (axis < 0) - axis += dstDims.size(); - - if (axis < 0 || axis >= static_cast(dstDims.size())) - IE_THROW() << op->get_friendly_name() << " Incorrect input parameters dimensions and axis number!"; - - size_t group = scOp->get_group(); - if (group == 0 || dstDims[axis] % group) - IE_THROW() << op->get_friendly_name() << " Group parameter must evenly divide the channel dimension!"; - - // Find number of dictionaries, index range and data length - own_dims[0] = 1; - for (int i = 0; i < axis; i++) - own_dims[0] *= dstDims[i]; - - for (size_t i = axis + 1; i < dstDims.size(); i++) - dataLength *= dstDims[i]; - - if (dataLength == 0) - IE_THROW() << op->get_friendly_name() << " Incorrect input parameters dimension!"; - - own_dims[1] = dstDims[axis] / group; - own_dims[2] = group; - ownStrides[0] = dstDims[axis]; - ownStrides[1] = 1; - ownStrides[2] = own_dims[1]; - work_amount_dst = ownStrides[0] * own_dims[0]; - - addConfig(op, {{TensorDescCreatorTypes::ncsp, details::convertPrecision(op->get_input_element_type(0))}}, - {{TensorDescCreatorTypes::ncsp, details::convertPrecision(op->get_input_element_type(0))}}); - } catch (InferenceEngine::Exception &ex) { - errorMsg = ex.what(); - throw; - } - } - - StatusCode execute(std::vector& inputs, std::vector& outputs, ResponseDesc *resp) noexcept override { - switch (inputs[0]->getTensorDesc().getPrecision().size()) { - case 1: { - process_data::value_type>(inputs, outputs); - break; - } - case 2: { - process_data::value_type>(inputs, outputs); - break; - } - case 4: { - process_data::value_type>(inputs, outputs); - break; - } - case 8: { - process_data::value_type>(inputs, outputs); - break; - } - default: { - if (resp) { - std::string errorMsg = "ShuffleChannels layer does not support precision '" - + std::string(inputs[0]->getTensorDesc().getPrecision().name()) + "'"; - errorMsg.copy(resp->msg, sizeof(resp->msg) - 1); - } - return GENERAL_ERROR; - } - } - - return OK; - } - - template - void process_data(std::vector& inputs, std::vector& outputs) noexcept { - const T* src_data = inputs[0]->cbuffer().as() + - inputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding(); - T* dst_data = outputs[0]->cbuffer().as() + - outputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding(); - - if (dataLength > 1) { - // Vectorized & Parallel - parallel_nt(0, [&](const int ithr, const int nthr) { - size_t start = 0, end = 0, src_idx = 0; - size_t counters[CNTR_SIZE] = { 0 }; - splitter(work_amount_dst, nthr, ithr, start, end); - src_idx = initter(start, CNTR_SIZE, counters, own_dims, ownStrides); - for (size_t iwork = start, dst_idx = start * dataLength; iwork < end; ++iwork, dst_idx += dataLength) { - cpu_memcpy(&dst_data[dst_idx], &src_data[dataLength * src_idx], sizeof(T) * dataLength); - src_idx = updater(src_idx, CNTR_SIZE, counters, own_dims, ownStrides); - } - }); - } else { - // Parallel - parallel_nt(0, [&](const int ithr, const int nthr) { - size_t start = 0, end = 0, src_idx = 0; - size_t counters[CNTR_SIZE] = { 0 }; - splitter(work_amount_dst, nthr, ithr, start, end); - src_idx = initter(start, CNTR_SIZE, counters, own_dims, ownStrides); - for (size_t iwork = start; iwork < end; ++iwork) { - dst_data[iwork] = src_data[src_idx]; - src_idx = updater(src_idx, CNTR_SIZE, counters, own_dims, ownStrides); - } - }); - } - } - -private: - size_t dataLength = 1; - size_t work_amount_dst; - size_t own_dims[CNTR_SIZE]; - size_t ownStrides[CNTR_SIZE]; - - static const std::set _supported_precisions_sizes; -}; - -const std::set ShuffleChannelsImpl::_supported_precisions_sizes = {1, 2, 4, 8}; - -REG_FACTORY_FOR(ShuffleChannelsImpl, ShuffleChannels); - -} // namespace Cpu -} // namespace Extensions -} // namespace InferenceEngine diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/shuffle_channels.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/shuffle_channels.cpp index 86bcb113414..b36a9e0713b 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/shuffle_channels.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/shuffle_channels.cpp @@ -11,27 +11,19 @@ using namespace LayerTestsDefinitions; namespace { const std::vector netPrecisions = { - InferenceEngine::Precision::I8, InferenceEngine::Precision::U8, - InferenceEngine::Precision::I16, - InferenceEngine::Precision::I32, + InferenceEngine::Precision::U16, InferenceEngine::Precision::FP32 }; -const std::vector axes = {0, 1, 2, 3}; -const std::vector negativeAxes = {-4, -3, -2, -1}; -const std::vector groups = {1, 2, 3}; +const std::vector axes = {-4, -3, -2, -1, 0, 1, 2, 3}; +const std::vector groups = {1, 2, 3, 6}; const auto shuffleChannelsParams4D = ::testing::Combine( ::testing::ValuesIn(axes), ::testing::ValuesIn(groups) ); -const auto shuffleChannelsParamsNegativeAxis4D = ::testing::Combine( - ::testing::ValuesIn(negativeAxes), - ::testing::ValuesIn(groups) -); - INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels4D, ShuffleChannelsLayerTest, ::testing::Combine( shuffleChannelsParams4D, @@ -40,19 +32,7 @@ INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels4D, ShuffleChannelsLayerTest, ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), ::testing::Values(InferenceEngine::Layout::ANY), ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(std::vector({6, 6, 6, 6})), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ShuffleChannelsLayerTest::getTestCaseName); - -INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannelsNegativeAxis4D, ShuffleChannelsLayerTest, - ::testing::Combine( - shuffleChannelsParamsNegativeAxis4D, - ::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({6, 6, 6, 6})), + ::testing::Values(std::vector({12, 18, 30, 36})), ::testing::Values(CommonTestUtils::DEVICE_CPU)), ShuffleChannelsLayerTest::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/shuffle_channels.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/shuffle_channels.cpp new file mode 100644 index 00000000000..0548aad8c5e --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/shuffle_channels.cpp @@ -0,0 +1,222 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "test_utils/cpu_test_utils.hpp" +#include "ngraph_functions/builders.hpp" +#include "ngraph_functions/utils/ngraph_helpers.hpp" + +using namespace InferenceEngine; +using namespace CPUTestUtils; + +namespace CPULayerTestsDefinitions { + +typedef std::tuple< + LayerTestsDefinitions::shuffleChannelsLayerTestParamsSet, + CPUSpecificParams> ShuffleChannelsLayerCPUTestParamsSet; + +class ShuffleChannelsLayerCPUTest : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + LayerTestsDefinitions::shuffleChannelsLayerTestParamsSet basicParamsSet; + CPUSpecificParams cpuParams; + std::tie(basicParamsSet, cpuParams) = obj.param; + + std::ostringstream result; + result << LayerTestsDefinitions::ShuffleChannelsLayerTest::getTestCaseName( + testing::TestParamInfo(basicParamsSet, 0)); + + result << CPUTestsBase::getTestCaseName(cpuParams); + + return result.str(); + } + +protected: + void SetUp() { + LayerTestsDefinitions::shuffleChannelsLayerTestParamsSet basicParamsSet; + CPUSpecificParams cpuParams; + std::tie(basicParamsSet, cpuParams) = this->GetParam(); + + std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; + + LayerTestsDefinitions::shuffleChannelsSpecificParams shuffleChannelsParams; + std::vector inputShape; + Precision netPrecision; + std::tie(shuffleChannelsParams, netPrecision, inPrc, outPrc, inLayout, outLayout, inputShape, targetDevice) = basicParamsSet; + + int axis, group; + std::tie(axis, group) = shuffleChannelsParams; + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); + auto paramOuts = ngraph::helpers::convert2OutputVector( + ngraph::helpers::castOps2Nodes(params)); + auto shuffleChannels = std::dynamic_pointer_cast( + ngraph::builder::makeShuffleChannels(paramOuts[0], axis, group)); + shuffleChannels->get_rt_info() = getCPUInfo(); + ngraph::ResultVector results{std::make_shared(shuffleChannels)}; + function = std::make_shared(results, params, "shuffleChannels"); + + if (selectedType.empty()) { + selectedType = getPrimitiveType(); + } + selectedType.push_back('_'); + selectedType += netPrecision.name(); + } +}; + +TEST_P(ShuffleChannelsLayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + Run(); + CheckPluginRelatedResults(executableNetwork, "ShuffleChannels"); +} + +namespace { + +/* CPU PARAMS */ +std::vector filterCPUInfoForDevice4D() { + std::vector resCPUParams; + if (with_cpu_x86_avx512f()) { + resCPUParams.push_back(CPUSpecificParams{{nchw}, {nchw}, {"jit_avx512"}, "jit_avx512"}); + resCPUParams.push_back(CPUSpecificParams{{nhwc}, {nhwc}, {"jit_avx512"}, "jit_avx512"}); + } else if (with_cpu_x86_avx2()) { + resCPUParams.push_back(CPUSpecificParams{{nchw}, {nchw}, {"jit_avx2"}, "jit_avx2"}); + resCPUParams.push_back(CPUSpecificParams{{nhwc}, {nhwc}, {"jit_avx2"}, "jit_avx2"}); + } else if (with_cpu_x86_sse42()) { + resCPUParams.push_back(CPUSpecificParams{{nchw}, {nchw}, {"jit_sse42"}, "jit_sse42"}); + resCPUParams.push_back(CPUSpecificParams{{nhwc}, {nhwc}, {"jit_sse42"}, "jit_sse42"}); + } else { + resCPUParams.push_back(CPUSpecificParams{{nchw}, {nchw}, {"ref"}, "ref"}); + } + return resCPUParams; +} + +std::vector filterCPUInfoForDevice5D() { + std::vector resCPUParams; + if (with_cpu_x86_avx512f()) { + resCPUParams.push_back(CPUSpecificParams{{ncdhw}, {ncdhw}, {"jit_avx512"}, "jit_avx512"}); + resCPUParams.push_back(CPUSpecificParams{{ndhwc}, {ndhwc}, {"jit_avx512"}, "jit_avx512"}); + } else if (with_cpu_x86_avx2()) { + resCPUParams.push_back(CPUSpecificParams{{ncdhw}, {ncdhw}, {"jit_avx2"}, "jit_avx2"}); + resCPUParams.push_back(CPUSpecificParams{{ndhwc}, {ndhwc}, {"jit_avx2"}, "jit_avx2"}); + } else if (with_cpu_x86_sse42()) { + resCPUParams.push_back(CPUSpecificParams{{ncdhw}, {ncdhw}, {"jit_sse42"}, "jit_sse42"}); + resCPUParams.push_back(CPUSpecificParams{{ndhwc}, {ndhwc}, {"jit_sse42"}, "jit_sse42"}); + } else { + resCPUParams.push_back(CPUSpecificParams{{ncdhw}, {ncdhw}, {"ref"}, "ref"}); + } + return resCPUParams; +} + +std::vector filterCPUInfoForDevice4DBlock() { + std::vector resCPUParams; + if (with_cpu_x86_avx512f()) { + resCPUParams.push_back(CPUSpecificParams{{nChw16c}, {nChw16c}, {"jit_avx512"}, "jit_avx512"}); + } else if (with_cpu_x86_avx2()) { + resCPUParams.push_back(CPUSpecificParams{{nChw8c}, {nChw8c}, {"jit_avx2"}, "jit_avx2"}); + } else if (with_cpu_x86_sse42()) { + resCPUParams.push_back(CPUSpecificParams{{nChw8c}, {nChw8c}, {"jit_sse42"}, "jit_sse42"}); + } + return resCPUParams; +} + +std::vector filterCPUInfoForDevice5DBlock() { + std::vector resCPUParams; + if (with_cpu_x86_avx512f()) { + resCPUParams.push_back(CPUSpecificParams{{nCdhw16c}, {nCdhw16c}, {"jit_avx512"}, "jit_avx512"}); + } else if (with_cpu_x86_avx2()) { + resCPUParams.push_back(CPUSpecificParams{{nCdhw8c}, {nCdhw8c}, {"jit_avx2"}, "jit_avx2"}); + } else if (with_cpu_x86_sse42()) { + resCPUParams.push_back(CPUSpecificParams{{nCdhw8c}, {nCdhw8c}, {"jit_sse42"}, "jit_sse42"}); + } + return resCPUParams; +} +/* ========== */ + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::BF16, + InferenceEngine::Precision::I8 +}; + +const auto shuffleChannelsParams4D = ::testing::Combine( + ::testing::ValuesIn(std::vector{-4, -2, 0, 1, 2, 3}), + ::testing::ValuesIn(std::vector{1, 2, 4, 8}) +); + +const auto shuffleChannelsParams5D = ::testing::Combine( + ::testing::ValuesIn(std::vector{-5, -1, 0, 1, 2, 3, 4}), + ::testing::ValuesIn(std::vector{1, 2, 3, 6}) +); + +INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels4D, ShuffleChannelsLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + shuffleChannelsParams4D, + ::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({16, 24, 32, 40})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(filterCPUInfoForDevice4D())), + ShuffleChannelsLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels5D, ShuffleChannelsLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + shuffleChannelsParams5D, + ::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({12, 18, 12, 18, 24})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(filterCPUInfoForDevice5D())), + ShuffleChannelsLayerCPUTest::getTestCaseName); + +const auto shuffleChannelsParams4DBlock = ::testing::Combine( + ::testing::ValuesIn(std::vector{-4, -2, -1, 0, 2, 3}), + ::testing::ValuesIn(std::vector{1, 2, 4, 8}) +); + +const auto shuffleChannelsParams5DBlock = ::testing::Combine( + ::testing::ValuesIn(std::vector{-5, -2, -1, 0, 2, 3, 4}), + ::testing::ValuesIn(std::vector{1, 2, 3, 6}) +); + +INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels4DBlock, ShuffleChannelsLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + shuffleChannelsParams4DBlock, + ::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({40, 32, 24, 16})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(filterCPUInfoForDevice4DBlock())), + ShuffleChannelsLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_ShuffleChannels5DBlock, ShuffleChannelsLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + shuffleChannelsParams5DBlock, + ::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({18, 12, 18, 12, 30})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(filterCPUInfoForDevice5DBlock())), + ShuffleChannelsLayerCPUTest::getTestCaseName); + +} // namespace + +} // namespace CPULayerTestsDefinitions From 9248a5887d9680317117cc191d2e0c237a00a9ab Mon Sep 17 00:00:00 2001 From: Vladimir Zinoviev Date: Thu, 13 May 2021 15:03:23 +0300 Subject: [PATCH 49/99] [LPT] Split mixed precision support (#5596) --- .../src/split.cpp | 3 +- .../split_transformation.cpp | 29 ++++++++--- .../lpt_ngraph_functions/split_function.hpp | 2 + .../src/split_function.cpp | 49 ++++++++++++------- 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/inference-engine/src/low_precision_transformations/src/split.cpp b/inference-engine/src/low_precision_transformations/src/split.cpp index 91a32f77868..4dcff39fc5d 100644 --- a/inference-engine/src/low_precision_transformations/src/split.cpp +++ b/inference-engine/src/low_precision_transformations/src/split.cpp @@ -83,7 +83,8 @@ bool SplitTransformation::transform(TransformationContext& context, ngraph::patt parent = subtract; } - const auto multiply = std::make_shared(parent, splitedMul[i]); + const auto multiply = std::make_shared>(parent, splitedMul[i]); + NetworkHelper::setOutDataPrecisionForTypeRelaxed(multiply, dequantization.multiply->get_output_element_type(0)); copy_runtime_info({ newSplit, multiply }, multiply); lastNodes.push_back(multiply); diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/split_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/split_transformation.cpp index 9f04c18a580..ae2ada651ef 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/split_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/split_transformation.cpp @@ -57,12 +57,19 @@ inline std::ostream& operator<<(std::ostream& os, return os; } -class SplitTransformation : public LayerTransformation, public testing::WithParamInterface { +typedef std::tuple < + ngraph::element::Type, + SplitTransformationTestValues +> SplitTransformationParams; + +class SplitTransformation : public LayerTransformation, public testing::WithParamInterface { public: void SetUp() override { - SplitTransformationTestValues testValues = GetParam(); + ngraph::element::Type precision = std::get<0>(GetParam()); + SplitTransformationTestValues testValues = std::get<1>(GetParam()); actualFunction = ngraph::builder::subgraph::SplitFunction::getOriginal( + precision, testValues.inputShape, testValues.actual.precisionBeforeDequantization, testValues.actual.dequantization, @@ -74,6 +81,7 @@ public: transformer.transform(actualFunction); referenceFunction = ngraph::builder::subgraph::SplitFunction::getReference( + precision, testValues.inputShape, testValues.expected.inputPrecision, testValues.expected.dequantizationBefore, @@ -83,11 +91,13 @@ public: testValues.numSplits); } - static std::string getTestCaseName(testing::TestParamInfo obj) { - const SplitTransformationTestValues testValues = obj.param; + static std::string getTestCaseName(testing::TestParamInfo obj) { + ngraph::element::Type precision = std::get<0>(obj.param); + SplitTransformationTestValues testValues = std::get<1>(obj.param); std::ostringstream result; - result << toString(testValues.params) << "_" << + result << precision << "_" << + toString(testValues.params) << "_" << testValues.inputShape << "_" << testValues.actual.precisionBeforeDequantization << "_" << testValues.actual.dequantization << "_" << @@ -106,6 +116,11 @@ TEST_P(SplitTransformation, CompareFunctions) { ASSERT_TRUE(res.first) << res.second; } +const std::vector precisions = { + ngraph::element::f32, + ngraph::element::f16 +}; + const std::vector testValues = { // U8 per tensor quantization { @@ -425,6 +440,8 @@ const std::vector testValues = { INSTANTIATE_TEST_CASE_P( smoke_LPT, SplitTransformation, - ::testing::ValuesIn(testValues), + ::testing::Combine( + ::testing::ValuesIn(precisions), + ::testing::ValuesIn(testValues)), SplitTransformation::getTestCaseName); } // namespace diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/split_function.hpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/split_function.hpp index 661c4c2e80c..46fa7cb9d61 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/split_function.hpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/split_function.hpp @@ -20,6 +20,7 @@ namespace subgraph { class SplitFunction { public: static std::shared_ptr getOriginal( + const element::Type& precision, const ngraph::Shape& inputShape, const ngraph::element::Type precisionBeforeDequantization, const ngraph::builder::subgraph::DequantizationOperations& dequantization, @@ -34,6 +35,7 @@ public: const size_t numSplit); static std::shared_ptr getReference( + const element::Type& precision, const ngraph::Shape& inputShape, const ngraph::element::Type inputPrecision, const ngraph::builder::subgraph::DequantizationOperations& dequantizationBefore, diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/split_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/split_function.cpp index 6820572c302..fe2e797cd32 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/split_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/split_function.cpp @@ -17,26 +17,29 @@ namespace ngraph { namespace builder { namespace subgraph { - std::shared_ptr SplitFunction::getOriginal( - const ngraph::Shape& inputShape, - const ngraph::element::Type precisionBeforeDequantization, - const ngraph::builder::subgraph::DequantizationOperations& dequantization, - const int64_t splitedAxis, - const size_t numSplits) { - const std::shared_ptr input = std::make_shared( - precisionBeforeDequantization, - ngraph::Shape(inputShape)); +std::shared_ptr SplitFunction::getOriginal( + const element::Type& precision, + const ngraph::Shape& inputShape, + const ngraph::element::Type precisionBeforeDequantization, + const ngraph::builder::subgraph::DequantizationOperations& dequantization, + const int64_t splitedAxis, + const size_t numSplits) { + const std::shared_ptr input = std::make_shared( + precisionBeforeDequantization, + ngraph::Shape(inputShape)); - const std::shared_ptr dequantizationOp = makeDequantization(input, dequantization); - const auto constant = std::make_shared(element::i64, Shape{ }, splitedAxis); - const std::shared_ptr split = std::make_shared(dequantizationOp, constant, numSplits); + auto dequantizationStructure = dequantization; + dequantizationStructure.multiply.outPrecision = precision; + const std::shared_ptr dequantizationOp = makeDequantization(input, dequantization); + const auto constant = std::make_shared(element::i64, Shape{ }, splitedAxis); + const std::shared_ptr split = std::make_shared(dequantizationOp, constant, numSplits); - ngraph::ResultVector results; - for (size_t i = 0; i < numSplits; ++i) { - results.push_back(std::make_shared(split->output(i))); - } - return std::make_shared(results, ngraph::ParameterVector{ input }, "SplitFunction"); + ngraph::ResultVector results; + for (size_t i = 0; i < numSplits; ++i) { + results.push_back(std::make_shared(split->output(i))); } + return std::make_shared(results, ngraph::ParameterVector{ input }, "SplitFunction"); +} std::shared_ptr SplitFunction::getOriginal( const ngraph::element::Type originalFunctionPrecision, @@ -67,6 +70,7 @@ std::shared_ptr SplitFunction::getOriginal( } std::shared_ptr SplitFunction::getReference( + const element::Type& precision, const ngraph::Shape& inputShape, const ngraph::element::Type inputPrecision, const ngraph::builder::subgraph::DequantizationOperations& dequantizationBefore, @@ -86,8 +90,15 @@ std::shared_ptr SplitFunction::getReference( ngraph::ResultVector results; for (size_t i = 0; i < numSplit; ++i) { - results.push_back(std::make_shared( - dequantizationAfter.empty() ? split->output(i) : makeDequantization(split->output(i), dequantizationAfter[i]))); + if (!dequantizationAfter.empty()) { + auto dequantizationStructure = dequantizationAfter[i]; + if (!dequantizationStructure.multiply.empty()) { + dequantizationStructure.multiply.outPrecision = precision; + } + results.push_back(std::make_shared(makeDequantization(split->output(i), dequantizationAfter[i]))); + } else { + results.push_back(std::make_shared(split->output(i))); + } } return std::make_shared(results, ngraph::ParameterVector{ input }, "SplitTransformation"); } From 05b62258c78e55543f3864be4260745dc2013045 Mon Sep 17 00:00:00 2001 From: Krzysztof Bruniecki Date: Thu, 13 May 2021 15:31:23 +0200 Subject: [PATCH 50/99] [GNA] Improve CNN2D kernels/weights quantization (#5370) * Introduce heuristic for weight reducer * handle kernels 3x3 and 7x1 to avoid saturation * enable tests * issue 54140 --- .../gna_plugin/frontend/scale_factor_calc.hpp | 6 ++- .../src/gna_plugin/gna_graph_compiler.cpp | 7 ++- .../layers/gna_convolution_layer.hpp | 49 +++++++++++++++++++ .../single_layer_tests/convolution.cpp | 4 +- 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 inference-engine/src/gna_plugin/layers/gna_convolution_layer.hpp diff --git a/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp b/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp index 1a4dabd2db6..be31c9fabd1 100644 --- a/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp +++ b/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp @@ -14,6 +14,7 @@ #include #include "gna_upstream_iterator.hpp" #include "layers/gna_layer_info.hpp" +#include "layers/gna_convolution_layer.hpp" #include "gna_plugin_log.hpp" #include "gna_slope_scale.h" #include "runtime/pwl.h" @@ -1107,8 +1108,9 @@ class ScaleFactorPerLayer { double weights_reducer = 1.0; auto conv = dynamic_cast(wl); if (conv) { - auto channels_num = GetDataDimSize(conv->insData.front().lock(), InferenceEngine::DataDimName::C); - weights_reducer = MAX_VAL_2B_FEAT * scaleRange * channels_num / std::numeric_limits::max(); + const auto inDepth = GetDataDimSize(conv->insData.front().lock(), InferenceEngine::DataDimName::C); + weights_reducer = GNAConvolutionLayer::getWeightsReducer(*conv); + weights_reducer *= MAX_VAL_2B_FEAT * scaleRange * inDepth / std::numeric_limits::max(); weights_reducer = std::max(1.0, weights_reducer); } quant->_weights_quant.SetScale(quant->_weights_quant.GetScale() / weights_reducer); diff --git a/inference-engine/src/gna_plugin/gna_graph_compiler.cpp b/inference-engine/src/gna_plugin/gna_graph_compiler.cpp index 541bd142c3e..b085dcef7f4 100644 --- a/inference-engine/src/gna_plugin/gna_graph_compiler.cpp +++ b/inference-engine/src/gna_plugin/gna_graph_compiler.cpp @@ -30,6 +30,7 @@ #include "frontend/model_quantizer.hpp" #include "layers/layers_builder.hpp" #include "layers/gna_concat_layer.hpp" +#include "layers/gna_convolution_layer.hpp" #include "layers/gna_crop_layer.hpp" #include "layers/gna_fake_quantize_layer.hpp" #include "round_float_define.hpp" @@ -265,7 +266,7 @@ void GNAGraphCompiler::ConvolutionPrimitive(InferenceEngine::CNNLayerPtr layer) } // Map 2d convolution to 1d if it's possible - if (in_height > 1 && in_width > 1 && in_width == convolution._kernel_x && convolution._stride_x == 1) { + if (GNAConvolutionLayer::isMappableFrom2DTo1D(in_height, in_width, convolution._kernel_x, convolution._stride_x)) { in_width *= in_height; in_height = 1; out_width *= out_height; @@ -298,9 +299,7 @@ void GNAGraphCompiler::ConvolutionPrimitive(InferenceEngine::CNNLayerPtr layer) dnn->new_num_conv_columns = 0; } - // TODO: refine following condition - if (((in_channels > 1) && (in_height > 1) && (in_width > 1)) || // 3D input - (convolution._kernel_x != 1 && convolution._kernel_y != 1) || // 2D kernel + if (GNAConvolutionLayer::isConv2D(in_height, in_width, in_channels, convolution._kernel_y, convolution._kernel_x) || in_height != 1) { // TensorFlow default layout is NHWC // OpenVino Default layout is NCHW diff --git a/inference-engine/src/gna_plugin/layers/gna_convolution_layer.hpp b/inference-engine/src/gna_plugin/layers/gna_convolution_layer.hpp new file mode 100644 index 00000000000..e83d9b6c535 --- /dev/null +++ b/inference-engine/src/gna_plugin/layers/gna_convolution_layer.hpp @@ -0,0 +1,49 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +#include +#include "../gna_graph_tools.hpp" + +namespace GNAPluginNS { +struct GNAConvolutionLayer { + static bool isMappableFrom2DTo1D(const uint32_t inHeight, const uint32_t inWidth, const uint32_t kernelWidth, const uint32_t strideWidth) { + return inHeight > 1 && inWidth > 1 && inWidth == kernelWidth && strideWidth == 1; + } + + // 3D input or 2D kernel + static bool isConv2D(const uint32_t inHeight, const uint32_t inWidth, const uint32_t inDepth, + const uint32_t kernelHeight, const uint32_t kernelWidth) { + return (kernelHeight > 1 && kernelWidth > 1) || (inHeight > 1 && inWidth > 1 && inDepth > 1); + } + + static double getWeightsReducer(InferenceEngine::ConvolutionLayer& conv) { + using KRT = std::pair; + // Empirically determined weights reducers for 2D Convolution + // i.e.: + // for kernelSize >= 9 -> 1.3 + // for kernelSize in {7, 8} -> 1.2 + const std::vector< KRT > reducers{ {9, 1.3}, {7, 1.2} }; + auto reducer = 1.0; + const auto inDepth = GetDataDimSize(conv.insData.front().lock(), InferenceEngine::DataDimName::C); + const auto inHeight = GetDataDimSize(conv.insData.front().lock(), InferenceEngine::DataDimName::H); + const auto inWidth = GetDataDimSize(conv.insData.front().lock(), InferenceEngine::DataDimName::W); + if (isConv2D(inHeight, inWidth, inDepth, conv._kernel_y, conv._kernel_x) && + !isMappableFrom2DTo1D(inHeight, inWidth, conv._kernel_x, conv._stride_x)) { + const auto kernelSize = conv._kernel_x * conv._kernel_y; + auto r = std::lower_bound(reducers.begin(), reducers.end(), kernelSize, + [](const KRT& l, const KRT::first_type& r) {return l.first > r; }); + if (r != reducers.end()) + reducer = r->second; + } + return reducer; + } +}; +} // namespace GNAPluginNS diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/convolution.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/convolution.cpp index 79151f34c3b..6605857612a 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/convolution.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/convolution.cpp @@ -71,8 +71,8 @@ const std::vector> kernels2D = { {1, 3}, {1, 2}, {2, 2}, - // {7, 1}, TODO: fix accuracy failures, see issue 54140 - // {3, 3}, TODO: fix accuracy failures, see issue 54140 + {7, 1}, + {3, 3}, }; const std::vector> strides2D = { {1, 1}, From 40ffca6fa2a949ce085bb1abaf677076520c4437 Mon Sep 17 00:00:00 2001 From: Shoujiang Ma Date: Thu, 13 May 2021 22:04:38 +0800 Subject: [PATCH 51/99] [Auto Plugin] Auto plugin component in IE (#5366) * Implement AUTO plugin Usage: 1. -d AUTO 2. -d "" Signed-off-by: Shoujiang Ma * Add tests for AUTO plugin Signed-off-by: Shoujiang Ma * cleaned impl, that was incorrect from the async perspective, ansl also capturing the blobs in the constructor * Revert benchmark_app modification Signed-off-by: Shoujiang Ma * Address reviewer's comments: need CI tests to verify Signed-off-by: Shoujiang Ma Co-authored-by: myshevts --- inference-engine/src/CMakeLists.txt | 2 + .../src/auto_plugin/CMakeLists.txt | 19 ++ .../src/auto_plugin/auto_exec_network.cpp | 59 ++++++ .../src/auto_plugin/auto_exec_network.hpp | 51 +++++ .../src/auto_plugin/auto_infer_request.cpp | 39 ++++ .../src/auto_plugin/auto_infer_request.hpp | 40 ++++ .../src/auto_plugin/auto_plugin.cpp | 199 ++++++++++++++++++ .../src/auto_plugin/auto_plugin.hpp | 37 ++++ .../src/inference_engine/ie_core.cpp | 42 +++- .../behavior/config.cpp | 33 ++- .../behavior/core_integration.cpp | 22 +- .../behavior/core_threading_tests.cpp | 1 + .../behavior/exec_graph_info.cpp | 10 + .../behavior/infer_request.cpp | 10 + .../behavior/infer_request_callback.cpp | 11 + .../behavior/infer_request_config.cpp | 18 ++ .../behavior/infer_request_input.cpp | 11 + .../behavior/infer_request_output.cpp | 11 + .../behavior/perf_counters.cpp | 11 + .../behavior/set_preprocess.cpp | 25 +++ .../behavior/test_plugin.cpp | 25 +++ .../plugin/shared/include/behavior/config.hpp | 3 +- .../include/behavior/exec_graph_info.hpp | 5 +- .../shared/include/behavior/infer_request.hpp | 2 +- .../common_test_utils/test_constants.hpp | 1 + 25 files changed, 670 insertions(+), 17 deletions(-) create mode 100644 inference-engine/src/auto_plugin/CMakeLists.txt create mode 100644 inference-engine/src/auto_plugin/auto_exec_network.cpp create mode 100644 inference-engine/src/auto_plugin/auto_exec_network.hpp create mode 100644 inference-engine/src/auto_plugin/auto_infer_request.cpp create mode 100644 inference-engine/src/auto_plugin/auto_infer_request.hpp create mode 100644 inference-engine/src/auto_plugin/auto_plugin.cpp create mode 100644 inference-engine/src/auto_plugin/auto_plugin.hpp diff --git a/inference-engine/src/CMakeLists.txt b/inference-engine/src/CMakeLists.txt index 086c06fc167..cd78cd959ec 100644 --- a/inference-engine/src/CMakeLists.txt +++ b/inference-engine/src/CMakeLists.txt @@ -30,6 +30,8 @@ endif() add_subdirectory(hetero_plugin) +add_subdirectory(auto_plugin) + add_subdirectory(multi_device) add_subdirectory(transformations) diff --git a/inference-engine/src/auto_plugin/CMakeLists.txt b/inference-engine/src/auto_plugin/CMakeLists.txt new file mode 100644 index 00000000000..8556d8940ed --- /dev/null +++ b/inference-engine/src/auto_plugin/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +set (TARGET_NAME "AutoPlugin") + +file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) + +ie_add_plugin(NAME ${TARGET_NAME} + DEVICE_NAME "AUTO" + SOURCES ${SOURCES} ${HEADERS} + VERSION_DEFINES_FOR auto_plugin.cpp) + +target_link_libraries(${TARGET_NAME} PRIVATE inference_engine) + +ie_add_api_validator_post_build_step(TARGET ${TARGET_NAME}) + +set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) diff --git a/inference-engine/src/auto_plugin/auto_exec_network.cpp b/inference-engine/src/auto_plugin/auto_exec_network.cpp new file mode 100644 index 00000000000..0d691214835 --- /dev/null +++ b/inference-engine/src/auto_plugin/auto_exec_network.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include + +#include "ie_metric_helpers.hpp" +#include "auto_exec_network.hpp" +#include "auto_infer_request.hpp" + +namespace AutoPlugin { + using namespace InferenceEngine; + +AutoExecutableNetwork::AutoExecutableNetwork(const ExecutableNetwork& network, + const DeviceInformation& deviceInfo, + const bool needPerfCounters) : + _deviceInfo(deviceInfo), + _network(network), + _config(deviceInfo.config.begin(), deviceInfo.config.end()), + _needPerfCounters(needPerfCounters) { +} + +AutoExecutableNetwork::~AutoExecutableNetwork() = default; + +IInferRequestInternal::Ptr AutoExecutableNetwork::CreateInferRequestImpl(InputsDataMap networkInputs, + OutputsDataMap networkOutputs) { + auto inferRequest = _network.CreateInferRequest(); + return std::make_shared(networkInputs, networkOutputs, inferRequest); +} + +void AutoExecutableNetwork::Export(std::ostream& networkModel) { + _network.Export(networkModel); +} + +RemoteContext::Ptr AutoExecutableNetwork::GetContext() const { + return _network.GetContext(); +} + +InferenceEngine::CNNNetwork AutoExecutableNetwork::GetExecGraphInfo() { + return _network.GetExecGraphInfo(); +} + +Parameter AutoExecutableNetwork::GetMetric(const std::string &name) const { + return _network.GetMetric(name); +} + +void AutoExecutableNetwork::SetConfig(const std::map& config) { + _network.SetConfig(config); +} + +Parameter AutoExecutableNetwork::GetConfig(const std::string& name) const { + return _network.GetConfig(name); +} + +} // namespace AutoPlugin diff --git a/inference-engine/src/auto_plugin/auto_exec_network.hpp b/inference-engine/src/auto_plugin/auto_exec_network.hpp new file mode 100644 index 00000000000..635d9573b9d --- /dev/null +++ b/inference-engine/src/auto_plugin/auto_exec_network.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace AutoPlugin { + +using DeviceName = std::string; + +struct DeviceInformation { + DeviceName deviceName; + std::map config; +}; + +class AutoExecutableNetwork : public InferenceEngine::ExecutableNetworkThreadSafeDefault { +public: + using Ptr = std::shared_ptr; + + AutoExecutableNetwork(const InferenceEngine::ExecutableNetwork& network, + const DeviceInformation& deviceInfo, + const bool needPerfCounters = false); + + void Export(std::ostream& networkModel) override; + InferenceEngine::RemoteContext::Ptr GetContext() const override; + InferenceEngine::CNNNetwork GetExecGraphInfo() override; + InferenceEngine::Parameter GetMetric(const std::string &name) const override; + void SetConfig(const std::map& config) override; + InferenceEngine::Parameter GetConfig(const std::string& name) const override; + InferenceEngine::IInferRequestInternal::Ptr CreateInferRequestImpl(InferenceEngine::InputsDataMap networkInputs, + InferenceEngine::OutputsDataMap networkOutputs) override; + ~AutoExecutableNetwork() override; + + DeviceInformation _deviceInfo; + InferenceEngine::ExecutableNetwork _network; + std::unordered_map _config; + bool _needPerfCounters = false; +}; + +} // namespace AutoPlugin diff --git a/inference-engine/src/auto_plugin/auto_infer_request.cpp b/inference-engine/src/auto_plugin/auto_infer_request.cpp new file mode 100644 index 00000000000..0adc4ba0938 --- /dev/null +++ b/inference-engine/src/auto_plugin/auto_infer_request.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "auto_infer_request.hpp" +#include +#include + +namespace AutoPlugin { + using namespace InferenceEngine; + +AutoInferRequest::AutoInferRequest(const InputsDataMap& networkInputs, + const OutputsDataMap& networkOutputs, + const InferRequest& inferRequest) + : IInferRequestInternal(networkInputs, networkOutputs) + , _inferRequest(inferRequest) { +} + +std::map AutoInferRequest::GetPerformanceCounts() const { + return _inferRequest.GetPerformanceCounts(); +} + +void AutoInferRequest::InferImpl() { + _inferRequest.Infer(); +} + +void AutoInferRequest::SetBlob(const std::string& name, const InferenceEngine::Blob::Ptr& data) { + _inferRequest.SetBlob(name, data); +} + +Blob::Ptr AutoInferRequest::GetBlob(const std::string& name) { + return _inferRequest.GetBlob(name); +} + +void AutoInferRequest::Cancel() { + _inferRequest.Cancel(); +} + +} // namespace AutoPlugin diff --git a/inference-engine/src/auto_plugin/auto_infer_request.hpp b/inference-engine/src/auto_plugin/auto_infer_request.hpp new file mode 100644 index 00000000000..49da8a117e1 --- /dev/null +++ b/inference-engine/src/auto_plugin/auto_infer_request.hpp @@ -0,0 +1,40 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AutoPlugin { + +class AutoInferRequest : public InferenceEngine::IInferRequestInternal { +public: + using Ptr = std::shared_ptr; + explicit AutoInferRequest(const InferenceEngine::InputsDataMap& networkInputs, + const InferenceEngine::OutputsDataMap& networkOutputs, + const InferenceEngine::InferRequest& inferRequest); + std::map GetPerformanceCounts() const override; + void InferImpl() override; + void SetBlob(const std::string& name, const InferenceEngine::Blob::Ptr& data) override; + InferenceEngine::Blob::Ptr GetBlob(const std::string& name) override; + void Cancel() override; + +private: + InferenceEngine::InferRequest _inferRequest; +}; + +} // namespace AutoPlugin diff --git a/inference-engine/src/auto_plugin/auto_plugin.cpp b/inference-engine/src/auto_plugin/auto_plugin.cpp new file mode 100644 index 00000000000..692d8955a09 --- /dev/null +++ b/inference-engine/src/auto_plugin/auto_plugin.cpp @@ -0,0 +1,199 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "auto_plugin.hpp" + +namespace AutoPlugin { +namespace { + ConfigType mergeConfigs(ConfigType config, const ConfigType& local) { + for (auto && kvp : local) { + config[kvp.first] = kvp.second; + } + return config; + } + + DeviceInformation SelectDevice(const std::vector& metaDevices) { + for (auto& item : metaDevices) { + if (item.deviceName.find("CPU") == 0) { + return item; + } + } + IE_THROW(NotFound) << "No available device could be used"; + } +} // namespace + +AutoInferencePlugin::AutoInferencePlugin() { + _pluginName = "AUTO"; +} + +IE::ExecutableNetworkInternal::Ptr AutoInferencePlugin::LoadExeNetworkImpl(const IE::CNNNetwork& network, + const ConfigType& config) { + if (GetCore() == nullptr) { + IE_THROW() << "Please, work with AUTO device via InferencEngine::Core object"; + } + + if (network.getFunction() == nullptr) { + IE_THROW() << "AUTO device supports just ngraph network representation"; + } + + auto fullConfig = mergeConfigs(_config, config); + auto metaDevices = GetDeviceChoice(fullConfig); + + // FIXME: always select CPU device now + DeviceInformation selectedDevice = SelectDevice(metaDevices); + IE::ExecutableNetwork executableNetwork; + try { + executableNetwork = GetCore()->LoadNetwork(network, selectedDevice.deviceName, selectedDevice.config); + } catch(const IE::Exception &iie) { + IE_THROW() << "Failed to load network to device named " << selectedDevice.deviceName + << " with exception " << iie.what(); + } + + bool enablePerfCounters = false; + try { + enablePerfCounters = + executableNetwork.GetConfig(IE::PluginConfigParams::KEY_PERF_COUNT).as() == + IE::PluginConfigParams::YES; + } catch (...) { + } + + return std::make_shared(executableNetwork, + selectedDevice, + enablePerfCounters); +} + +IE::QueryNetworkResult AutoInferencePlugin::QueryNetwork(const IE::CNNNetwork& network, const ConfigType& config) const { + IE::QueryNetworkResult queryResult = {}; + if (GetCore() == nullptr) { + IE_THROW() << "Please, work with AUTO device via InferencEngine::Core object"; + } + + if (network.getFunction() == nullptr) { + IE_THROW() << "AUTO device supports just ngraph network representation"; + } + + auto fullConfig = mergeConfigs(_config, config); + auto metaDevices = GetDeviceChoice(fullConfig); + std::unordered_set supportedLayers; + for (auto&& value : metaDevices) { + try { + auto deviceQr = GetCore()->QueryNetwork(network, value.deviceName, value.config); + std::unordered_set deviceSupportedLayers; + for (auto &&layerQr : deviceQr.supportedLayersMap) { + deviceSupportedLayers.emplace(layerQr.first); + } + supportedLayers = supportedLayers.empty() + ? deviceSupportedLayers : (deviceSupportedLayers.empty() + ? supportedLayers : IE::details::Intersection( + supportedLayers, deviceSupportedLayers)); + break; + } catch (...) { + } + } + + for (auto&& supportedLayer : supportedLayers) { + queryResult.supportedLayersMap[supportedLayer] = GetName(); + } + return queryResult; +} + +IE::Parameter AutoInferencePlugin::GetConfig(const std::string& name, + const std::map & options) const { + auto it = _config.find(name); + if (it == _config.end()) { + IE_THROW() << "Unsupported config key: " << name; + } else { + return { it->second }; + } +} + +void AutoInferencePlugin::SetConfig(const ConfigType& config) { + for (auto && kvp : config) { + _config[kvp.first] = kvp.second; + } +} + +IE::Parameter AutoInferencePlugin::GetMetric(const std::string& name, + const std::map & options) const { + if (name == METRIC_KEY(SUPPORTED_METRICS)) { + std::vector metrics; + metrics.emplace_back(METRIC_KEY(SUPPORTED_METRICS)); + metrics.emplace_back(METRIC_KEY(FULL_DEVICE_NAME)); + metrics.emplace_back(METRIC_KEY(SUPPORTED_CONFIG_KEYS)); + metrics.emplace_back(METRIC_KEY(OPTIMIZATION_CAPABILITIES)); + IE_SET_METRIC_RETURN(SUPPORTED_METRICS, metrics); + } else if (name == METRIC_KEY(FULL_DEVICE_NAME)) { + std::string device_name = {"Inference Engine AUTO device"}; + IE_SET_METRIC_RETURN(FULL_DEVICE_NAME, device_name); + } else if (name == METRIC_KEY(SUPPORTED_CONFIG_KEYS)) { + std::vector configKeys; + IE_SET_METRIC_RETURN(SUPPORTED_CONFIG_KEYS, configKeys); + } else if (name == METRIC_KEY(OPTIMIZATION_CAPABILITIES)) { + std::vector capabilities = { "" }; + IE_SET_METRIC_RETURN(OPTIMIZATION_CAPABILITIES, capabilities); + } else { + IE_THROW() << "Unsupported metric key " << name; + } +} + +std::vector AutoInferencePlugin::GetDeviceChoice(const ConfigType& config) const { + std::vector metaDevices; + std::vector availableDevices = GetCore()->GetAvailableDevices(); + + auto getDeviceConfig = [&] (const DeviceName & deviceWithID) { + IE::DeviceIDParser deviceParser(deviceWithID); + std::string deviceName = deviceParser.getDeviceName(); + ConfigType tconfig = mergeConfigs(_config, config); + + // set device ID if any + std::string deviceIDLocal = deviceParser.getDeviceID(); + if (!deviceIDLocal.empty()) { + tconfig[IE::PluginConfigParams::KEY_DEVICE_ID] = deviceIDLocal; + } + + return GetSupportedConfig(tconfig, deviceName); + }; + + for (auto && d : availableDevices) { + if (d != _pluginName) { + metaDevices.push_back({ d, getDeviceConfig(d)}); + } + } + + if (metaDevices.empty()) { + IE_THROW() << "Please, check environment due to no supported devices can be used"; + } + + return metaDevices; +} + +//////////////////////////////////// private & protected functions /////////////////// +ConfigType AutoInferencePlugin::GetSupportedConfig(const ConfigType& config, + const std::string& deviceName) const { + std::vector supportedConfigKeys = GetCore()->GetMetric(deviceName, METRIC_KEY(SUPPORTED_CONFIG_KEYS)); + ConfigType supportedConfig; + for (auto&& key : supportedConfigKeys) { + auto itKey = config.find(key); + if (config.end() != itKey) { + supportedConfig[key] = itKey->second; + } + } + return supportedConfig; +} + +// define CreatePluginEngine to create plugin instance +static const IE::Version version = {{2, 1}, CI_BUILD_NUMBER, "AutoPlugin"}; +IE_DEFINE_PLUGIN_CREATE_FUNCTION(AutoInferencePlugin, version) +} // namespace AutoPlugin diff --git a/inference-engine/src/auto_plugin/auto_plugin.hpp b/inference-engine/src/auto_plugin/auto_plugin.hpp new file mode 100644 index 00000000000..a2a885d4f1f --- /dev/null +++ b/inference-engine/src/auto_plugin/auto_plugin.hpp @@ -0,0 +1,37 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include "auto_exec_network.hpp" + +namespace AutoPlugin { +namespace IE = InferenceEngine; +using ConfigType = std::map; + +class AutoInferencePlugin : public IE::InferencePluginInternal { +public: + AutoInferencePlugin(); + ~AutoInferencePlugin() = default; + IE::ExecutableNetworkInternal::Ptr LoadExeNetworkImpl(const IE::CNNNetwork& network, const ConfigType& config) override; + IE::QueryNetworkResult QueryNetwork(const IE::CNNNetwork& network, const ConfigType& config) const override; + IE::Parameter GetMetric(const std::string& name, const std::map& options) const override; + IE::Parameter GetConfig(const std::string& name, const std::map & options) const override; + void SetConfig(const ConfigType& config) override; + +private: + std::vector GetDeviceChoice(const ConfigType& config) const; + +protected: + ConfigType GetSupportedConfig(const ConfigType& config, const AutoPlugin::DeviceName & deviceName) const; +}; + +} // namespace AutoPlugin diff --git a/inference-engine/src/inference_engine/ie_core.cpp b/inference-engine/src/inference_engine/ie_core.cpp index 14cd4d9a40e..8d9a6bb475c 100644 --- a/inference-engine/src/inference_engine/ie_core.cpp +++ b/inference-engine/src/inference_engine/ie_core.cpp @@ -51,6 +51,9 @@ Parsed parseDeviceNameIntoConfig(const std::string& deviceName, const std::ma deviceName_ = "MULTI"; config_[InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES] = deviceName.substr(6); } else { + if (deviceName_.empty()) { + deviceName_ = "AUTO"; + } DeviceIDParser parser(deviceName_); deviceName_ = parser.getDeviceName(); std::string deviceIDLocal = parser.getDeviceID(); @@ -583,6 +586,15 @@ public: } } + // AUTO case + { + if (deviceName.find("AUTO:") == 0) { + IE_THROW() + << "You can get specific metrics with the GetMetric only for the AUTO itself (without devices). " + "To get individual devices's metrics call GetMetric for each device separately"; + } + } + auto parsed = parseDeviceNameIntoConfig(deviceName); // we need to return a copy of Parameter object which is created on Core side, @@ -753,7 +765,7 @@ public: * @brief Sets config values for a plugin or set of plugins * @param deviceName A device name to set config to * If empty, config is set for all the plugins / plugin's meta-data - * @note `deviceName` is not allowed in form of MULTI:CPU, HETERO:FPGA,CPU + * @note `deviceName` is not allowed in form of MULTI:CPU, HETERO:FPGA,CPU, AUTO:CPU * just simple forms like CPU, GPU, MULTU, GPU.0, etc */ void SetConfigForPlugins(const std::map& configMap, const std::string& deviceName) { @@ -909,6 +921,10 @@ RemoteContext::Ptr Core::CreateContext(const std::string& deviceName, const Para if (deviceName.find("MULTI") == 0) { IE_THROW() << "MULTI device does not support remote context"; } + if (deviceName.find("AUTO") == 0) { + IE_THROW() << "AUTO device does not support remote context"; + } + auto parsed = parseDeviceNameIntoConfig(deviceName, params); return _impl->GetCPPPluginByName(parsed._deviceName).CreateContext(parsed._config); @@ -921,6 +937,9 @@ RemoteContext::Ptr Core::GetDefaultContext(const std::string& deviceName) { if (deviceName.find("MULTI") == 0) { IE_THROW() << "MULTI device does not support remote context"; } + if (deviceName.find("AUTO") == 0) { + IE_THROW() << "AUTO device does not support remote context"; + } auto parsed = parseDeviceNameIntoConfig(deviceName, ParamMap()); return _impl->GetCPPPluginByName(parsed._deviceName).GetDefaultContext(parsed._config); @@ -935,6 +954,10 @@ void Core::AddExtension(IExtensionPtr extension, const std::string& deviceName_) IE_THROW() << "MULTI device does not support extensions. Please, set extensions directly to fallback devices"; } + if (deviceName_.find("AUTO") == 0) { + IE_THROW() + << "AUTO device does not support extensions. Please, set extensions directly to fallback devices"; + } _impl->AddExtension(extension); } @@ -954,6 +977,9 @@ ExecutableNetwork Core::ImportNetwork(const std::string& modelFileName, const st if (deviceName.find("MULTI") == 0) { IE_THROW() << "MULTI device does not support ImportNetwork"; } + if (deviceName.find("AUTO") == 0) { + IE_THROW() << "AUTO device does not support ImportNetwork"; + } auto parsed = parseDeviceNameIntoConfig(deviceName, config); return _impl->GetCPPPluginByName(parsed._deviceName).ImportNetwork(modelFileName, parsed._config); @@ -999,6 +1025,12 @@ void Core::SetConfig(const std::map& config, const std "You can configure the devices with SetConfig before creating the MULTI on top."; } + // AUTO case + if (deviceName.find("AUTO:") == 0) { + IE_THROW() << "SetConfig is supported only for AUTO itself (without devices). " + "You can configure the devices with SetConfig before creating the AUTO on top."; + } + // GPU.0, FPGA.1 cases if (deviceName.find(".") != std::string::npos) { IE_THROW() << "SetConfig is supported only for device family itself (without particular device .#). " @@ -1030,6 +1062,14 @@ Parameter Core::GetConfig(const std::string& deviceName, const std::string& name "GetConfig is also possible for the individual devices before creating the MULTI on top."; } } + // AUTO case + { + if (deviceName.find("AUTO:") == 0) { + IE_THROW() + << "You can only GetConfig of the AUTO itself (without devices). " + "GetConfig is also possible for the individual devices before creating the AUTO on top."; + } + } auto parsed = parseDeviceNameIntoConfig(deviceName); diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/config.cpp index e2a09cc6e80..00081645107 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/config.cpp @@ -42,6 +42,10 @@ namespace { {InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_LIMIT, "10"}} }; + const std::vector> AutoConfigs = { + {} + }; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, CorrectConfigTests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -56,6 +60,13 @@ namespace { ::testing::ValuesIn(MultiConfigs)), CorrectConfigTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, CorrectConfigTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(AutoConfigs)), + CorrectConfigTests::getTestCaseName); + const std::vector> inconfigs = { {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, "OFF"}}, {{InferenceEngine::PluginConfigParams::KEY_CPU_BIND_THREAD, "OFF"}}, @@ -75,7 +86,6 @@ namespace { {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}} }; - INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, CorrectConfigAPITests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -90,6 +100,13 @@ namespace { ::testing::ValuesIn(multiconf)), CorrectConfigAPITests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, CorrectConfigAPITests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(AutoConfigs)), + CorrectConfigAPITests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, IncorrectConfigTests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -104,6 +121,13 @@ namespace { ::testing::ValuesIn(multiinconfigs)), IncorrectConfigTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, IncorrectConfigTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(inconfigs)), + IncorrectConfigTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, IncorrectConfigAPITests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -118,4 +142,11 @@ namespace { ::testing::ValuesIn(multiinconfigs)), IncorrectConfigAPITests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, IncorrectConfigAPITests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(inconfigs)), + IncorrectConfigAPITests::getTestCaseName); + } // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/core_integration.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/core_integration.cpp index 79ff8fe40e8..cbab53c64a2 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/core_integration.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/core_integration.cpp @@ -31,11 +31,11 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( smoke_IEClassGetMetricTest, IEClassGetMetricTest_SUPPORTED_CONFIG_KEYS, - ::testing::Values("CPU", "MULTI", "HETERO")); + ::testing::Values("CPU", "MULTI", "HETERO", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassGetMetricTest, IEClassGetMetricTest_SUPPORTED_METRICS, - ::testing::Values("CPU", "MULTI", "HETERO")); + ::testing::Values("CPU", "MULTI", "HETERO", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassGetMetricTest, IEClassGetMetricTest_AVAILABLE_DEVICES, @@ -43,11 +43,11 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( smoke_IEClassGetMetricTest, IEClassGetMetricTest_FULL_DEVICE_NAME, - ::testing::Values("CPU", "MULTI", "HETERO")); + ::testing::Values("CPU", "MULTI", "HETERO", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassGetMetricTest, IEClassGetMetricTest_OPTIMIZATION_CAPABILITIES, - ::testing::Values("CPU")); + ::testing::Values("CPU", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassGetMetricTest, IEClassGetMetricTest_RANGE_FOR_ASYNC_INFER_REQUESTS, @@ -59,11 +59,11 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( smoke_IEClassGetMetricTest, IEClassGetMetricTest_ThrowUnsupported, - ::testing::Values("CPU", "MULTI", "HETERO")); + ::testing::Values("CPU", "MULTI", "HETERO", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassGetConfigTest, IEClassGetConfigTest_ThrowUnsupported, - ::testing::Values("CPU", "MULTI", "HETERO")); + ::testing::Values("CPU", "MULTI", "HETERO", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassGetAvailableDevices, IEClassGetAvailableDevices, @@ -83,23 +83,23 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( smoke_IEClassExecutableNetworkGetMetricTest, IEClassExecutableNetworkGetMetricTest_SUPPORTED_CONFIG_KEYS, - ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU")); + ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassExecutableNetworkGetMetricTest, IEClassExecutableNetworkGetMetricTest_SUPPORTED_METRICS, - ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU")); + ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassExecutableNetworkGetMetricTest, IEClassExecutableNetworkGetMetricTest_NETWORK_NAME, - ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU")); + ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassExecutableNetworkGetMetricTest, IEClassExecutableNetworkGetMetricTest_OPTIMAL_NUMBER_OF_INFER_REQUESTS, - ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU")); + ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU", "AUTO")); INSTANTIATE_TEST_CASE_P( smoke_IEClassExecutableNetworkGetMetricTest, IEClassExecutableNetworkGetMetricTest_ThrowsUnsupported, - ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU")); + ::testing::Values("CPU", "MULTI:CPU", "HETERO:CPU", "AUTO")); // // Executable Network GetConfig / SetConfig diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/core_threading_tests.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/core_threading_tests.cpp index 3802907904d..09806c12e16 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/core_threading_tests.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/core_threading_tests.cpp @@ -10,6 +10,7 @@ const Params params[] = { std::tuple{ CommonTestUtils::DEVICE_CPU, {{ CONFIG_KEY(PERF_COUNT), CONFIG_VALUE(YES) }}}, std::tuple{ CommonTestUtils::DEVICE_HETERO, {{ "TARGET_FALLBACK", CommonTestUtils::DEVICE_CPU }}}, std::tuple{ CommonTestUtils::DEVICE_MULTI, {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU }}}, + std::tuple{ CommonTestUtils::DEVICE_AUTO, {{}}}, }; const Params paramsStreams[] = { diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/exec_graph_info.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/exec_graph_info.cpp index 32c789d1f54..474b6f6c7ce 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/exec_graph_info.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/exec_graph_info.cpp @@ -18,6 +18,9 @@ namespace { const std::vector> multiConfigs = { {{ InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}} }; + const std::vector> autoConfigs = { + {} + }; INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, ExecGraphTests, ::testing::Combine( @@ -32,4 +35,11 @@ namespace { ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), ExecGraphTests::getTestCaseName); + + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, ExecGraphTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + ExecGraphTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request.cpp index 4323e803058..1f0bebc3fcb 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request.cpp @@ -24,6 +24,8 @@ namespace { {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} }; + const std::vector> Autoconfigs = {{}}; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, InferRequestTests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -37,4 +39,12 @@ namespace { ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(Multiconfigs)), InferRequestTests::getTestCaseName); + + INSTANTIATE_TEST_CASE_P(smoke_AutoPlugin_BehaviorTests, InferRequestTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + InferRequestTests::getTestCaseName); + } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_callback.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_callback.cpp index 6d616300a5c..e85179ac5fb 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_callback.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_callback.cpp @@ -23,6 +23,10 @@ const std::vector> multiConfigs = { {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} }; +const std::vector> autoConfigs = { + {} +}; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, CallbackTests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -36,4 +40,11 @@ INSTANTIATE_TEST_CASE_P(smoke_Multi_BehaviorTests, CallbackTests, ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), CallbackTests::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, CallbackTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + CallbackTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_config.cpp index 40f6c58d9aa..13f6acf76d8 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_config.cpp @@ -48,6 +48,10 @@ namespace { {InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_LIMIT, "10"}} }; + const std::vector> autoConfigs = { + {} + }; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, InferConfigTests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -62,6 +66,13 @@ namespace { ::testing::ValuesIn(multiConfigs)), InferConfigTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, InferConfigTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + InferConfigTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, InferConfigInTests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -75,4 +86,11 @@ namespace { ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(MultiInConfigs)), InferConfigInTests::getTestCaseName); + + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, InferConfigInTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + InferConfigInTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_input.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_input.cpp index efd3684a5c0..5cada3a10a5 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_input.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_input.cpp @@ -27,6 +27,10 @@ namespace { {InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}} }; + const std::vector> autoConfigs = { + {} + }; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, InferRequestInputTests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -41,4 +45,11 @@ namespace { ::testing::ValuesIn(multiConfigs)), InferRequestInputTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, InferRequestInputTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + InferRequestInputTests::getTestCaseName); + } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_output.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_output.cpp index d041a358182..18815f3b937 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_output.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_output.cpp @@ -23,6 +23,10 @@ namespace { {InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}} }; + const std::vector> autoConfigs = { + {} + }; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, InferRequestOutputTests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -37,4 +41,11 @@ namespace { ::testing::ValuesIn(multiConfigs)), InferRequestOutputTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, InferRequestOutputTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + InferRequestOutputTests::getTestCaseName); + } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/perf_counters.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/perf_counters.cpp index ff9a8063ae0..cde809a64dd 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/perf_counters.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/perf_counters.cpp @@ -15,6 +15,10 @@ namespace { {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} }; + const std::vector> Autoconfigs = { + {} + }; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, PerfCountersTest, ::testing::Combine( ::testing::Values(InferenceEngine::Precision::FP32), @@ -29,4 +33,11 @@ namespace { ::testing::ValuesIn(Multiconfigs)), PerfCountersTest::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, PerfCountersTest, + ::testing::Combine( + ::testing::Values(InferenceEngine::Precision::FP32), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + PerfCountersTest::getTestCaseName); + } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_preprocess.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_preprocess.cpp index 6086c902524..d8e228061c8 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_preprocess.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_preprocess.cpp @@ -28,6 +28,10 @@ namespace { {{ InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}} }; + const std::vector> autoConfigs = { + {} + }; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, PreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -49,6 +53,13 @@ namespace { ::testing::ValuesIn(multiConfigs)), PreprocessTest::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, PreprocessTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + PreprocessTest::getTestCaseName); + const std::vector ioPrecisions = { InferenceEngine::Precision::FP32, @@ -106,4 +117,18 @@ namespace { ::testing::ValuesIn(multiConfigs)), PreprocessConversionTest::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, PreprocessConversionTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(netLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + PreprocessConversionTest::getTestCaseName); + } // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/test_plugin.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/test_plugin.cpp index 286563e3217..ea61aa7e055 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/test_plugin.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/test_plugin.cpp @@ -39,6 +39,10 @@ namespace { {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}} }; + const std::vector> Autoconfigs = { + {} + }; + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, BehaviorTestOutput, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -53,6 +57,13 @@ namespace { ::testing::ValuesIn(MultiConfigsInputOutput)), BehaviorTestOutput::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, BehaviorTestOutput, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + BehaviorTestOutput::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, BehaviorTests, ::testing::Combine( ::testing::Values(InferenceEngine::Precision::FP32), @@ -67,6 +78,13 @@ namespace { ::testing::ValuesIn(MultiConfigs)), BehaviorTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, BehaviorTests, + ::testing::Combine( + ::testing::Values(InferenceEngine::Precision::FP32), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + BehaviorTests::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, BehaviorTestInput, ::testing::Combine( ::testing::ValuesIn(netPrecisions), @@ -81,4 +99,11 @@ namespace { ::testing::ValuesIn(MultiConfigsInputOutput)), BehaviorTestInput::getTestCaseName); + INSTANTIATE_TEST_CASE_P(smoke_Auto_BehaviorTests, BehaviorTestInput, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + BehaviorTestInput::getTestCaseName); + } // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp index 2e2f91067f7..833398f670b 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp @@ -58,7 +58,8 @@ namespace BehaviorTestsDefinitions { // Create CNNNetwork from ngrpah::Function InferenceEngine::CNNNetwork cnnNet(function); if (targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { + targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos) { ASSERT_NO_THROW(ie->GetMetric(targetDevice, METRIC_KEY(SUPPORTED_CONFIG_KEYS))); ASSERT_THROW(ie->SetConfig(configuration, targetDevice), InferenceEngine::Exception); diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp index 6c92a9e45fa..c4e0f4ee395 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp @@ -72,12 +72,13 @@ TEST_P(ExecGraphTests, CheckExecGraphInfoBeforeExecution) { const auto originalLayers = function->get_ops(); std::map originalLayersMap; for (const auto &layer : originalLayers) { - if (layer->description() == "Result" && targetDevice != CommonTestUtils::DEVICE_CPU) + if (layer->description() == "Result" && + targetDevice != CommonTestUtils::DEVICE_CPU && + targetDevice != CommonTestUtils::DEVICE_AUTO) continue; originalLayersMap[layer->get_friendly_name()] = 0; } int IteratorForLayersConstant = 0; - if (auto function = execGraph.getFunction()) { for (const auto & op : function->get_ops()) { const auto & rtInfo = op->get_rt_info(); diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp index 7adc5edbd4c..3a1efd4b07f 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp @@ -324,7 +324,7 @@ TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetBlobForAsync) { ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); blob->deallocate(); ASSERT_THROW(req.Infer(), InferenceEngine::Exception); - ASSERT_THROW(req.StartAsync(), InferenceEngine::Exception); + ASSERT_THROW({ req.StartAsync(); req.Wait(); }, InferenceEngine::Exception); } TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetAndSetBlob) { diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp b/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp index 327439cfa65..a8089bd3937 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp @@ -6,6 +6,7 @@ namespace CommonTestUtils { +const char DEVICE_AUTO[] = "AUTO"; const char DEVICE_CPU[] = "CPU"; const char DEVICE_GNA[] = "GNA"; const char DEVICE_GPU[] = "GPU"; From 5af767a0a2e91d2031b847e23fd3019093264446 Mon Sep 17 00:00:00 2001 From: Sergey Lyubimtsev Date: Thu, 13 May 2021 20:20:41 +0300 Subject: [PATCH 52/99] Add MO extras requires for supported DL frameworks (#5615) * Add extras requires for supported DL frameworks * fix pylint issues * codestyle (PEP8) * Indentation --- model-optimizer/setup.py | 105 +++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 44 deletions(-) diff --git a/model-optimizer/setup.py b/model-optimizer/setup.py index 26a28ae0802..c18c1d11947 100644 --- a/model-optimizer/setup.py +++ b/model-optimizer/setup.py @@ -11,27 +11,34 @@ $ python setup.py sdist bdist_wheel import os import re +from pathlib import Path from shutil import copyfile from setuptools import setup, find_packages from setuptools.command.install import install from setuptools.command.build_py import build_py PACKAGE_NAME = 'mo' +SETUP_DIR = Path(__file__).resolve().parent + + +def read_text(path): + return (SETUP_DIR / path).read_text() + # Detect all the framework specific requirements_*.txt files. requirements_txt = [] py_modules = [] -for name in os.listdir(): - if re.match(r'requirements(.*)\.txt', name): - requirements_txt.append(name) - if re.match(r'mo(.*)\.py', name): - py_modules.append(name.split('.')[0]) +for item in os.listdir(): + if re.match(r'requirements(.*)\.txt', item): + requirements_txt.append(item) + if re.match(r'mo(.*)\.py', item): + py_modules.append(item.split('.')[0]) # Minimal set of dependencies deps_whitelist = ('networkx', 'defusedxml', 'numpy') deps = [] -with open('requirements.txt', 'rt') as f: - for line in f.read().split('\n'): +with open('requirements.txt', 'rt') as req_file: + for line in req_file.read().split('\n'): if line.startswith(deps_whitelist): deps.append(line) @@ -42,23 +49,24 @@ class InstallCmd(install): # Create requirements.txt files for all the frameworks for name in requirements_txt: path = os.path.join(self.install_purelib, PACKAGE_NAME, name) - with open(path, 'wt') as f: - f.write('\n'.join(deps)) + with open(path, 'wt') as common_reqs_file: + common_reqs_file.write('\n'.join(deps)) # Add version.txt if exists version_txt = 'version.txt' if os.path.exists(version_txt): copyfile(os.path.join(version_txt), - os.path.join(self.install_purelib, PACKAGE_NAME, version_txt)) + os.path.join(self.install_purelib, + PACKAGE_NAME, version_txt)) path = os.path.join(self.install_purelib, PACKAGE_NAME, '__init__.py') - with open(path, 'wt') as f: - f.write('import os, sys\n') - f.write('from {} import mo\n'.format(PACKAGE_NAME)) + with open(path, 'wt') as init_file: + init_file.write('import os, sys\n') + init_file.write('from {} import mo\n'.format(PACKAGE_NAME)) # This is required to fix internal imports - f.write('sys.path.append(os.path.dirname(__file__))\n') + init_file.write('sys.path.append(os.path.dirname(__file__))\n') # We install a package into custom folder "PACKAGE_NAME". # Redirect import to model-optimizer/mo/__init__.py - f.write('sys.modules["mo"] = mo') + init_file.write('sys.modules["mo"] = mo') class BuildCmd(build_py): @@ -74,33 +82,42 @@ class BuildCmd(build_py): packages = find_packages() packages = [PACKAGE_NAME + '.' + p for p in packages] -setup(name='openvino-mo', - version='0.0.0', - author='Intel Corporation', - author_email='openvino_pushbot@intel.com', - url='https://github.com/openvinotoolkit/openvino', - packages=packages, - package_dir={PACKAGE_NAME: '.'}, - py_modules=py_modules, - cmdclass={ - 'install': InstallCmd, - 'build_py': BuildCmd, - }, - entry_points={ - 'console_scripts': [ - 'mo = mo.__main__:main', - ], - }, - package_data={ - 'mo.mo.front.caffe.proto': ['*.proto'], - 'mo.extensions.front.mxnet': ['*.json'], - 'mo.extensions.front.onnx': ['*.json'], - 'mo.extensions.front.tf': ['*.json'], - }, - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - ], - install_requires=deps, +setup( + name='openvino-mo', + version='0.0.0', + author='Intel Corporation', + author_email='openvino_pushbot@intel.com', + url='https://github.com/openvinotoolkit/openvino', + packages=packages, + package_dir={PACKAGE_NAME: '.'}, + py_modules=py_modules, + cmdclass={ + 'install': InstallCmd, + 'build_py': BuildCmd, + }, + entry_points={ + 'console_scripts': [ + 'mo = mo.__main__:main', + ], + }, + package_data={ + 'mo.mo.front.caffe.proto': ['*.proto'], + 'mo.extensions.front.mxnet': ['*.json'], + 'mo.extensions.front.onnx': ['*.json'], + 'mo.extensions.front.tf': ['*.json'], + }, + extras_require={ + 'caffe': read_text('requirements_caffe.txt'), + 'kaldi': read_text('requirements_kaldi.txt'), + 'mxnet': read_text('requirements_mxnet.txt'), + 'onnx': read_text('requirements_onnx.txt'), + 'tensorflow': read_text('requirements_tf.txt'), + 'tensorflow2': read_text('requirements_tf2.txt'), + }, + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + ], + install_requires=deps, ) From f88611e5a2fee201b7fa4258ad1498a1273adcac Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 13 May 2021 21:53:08 +0300 Subject: [PATCH 53/99] Removed FPGA constant from tests (#5626) --- .../behavior/core_integration.cpp | 15 --------------- .../plugin/shared/include/behavior/config.hpp | 7 +++---- .../include/behavior/infer_request_config.hpp | 2 +- .../common_test_utils/test_constants.hpp | 1 - 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/core_integration.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/core_integration.cpp index 37cfad33c09..8edb52954a8 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/core_integration.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/core_integration.cpp @@ -40,21 +40,6 @@ INSTANTIATE_TEST_CASE_P( using IEClassNetworkTestP_VPU = IEClassNetworkTestP; -TEST_P(IEClassNetworkTestP_VPU, smoke_ImportNetworkNoThrowIfNoDeviceName) { - SKIP_IF_CURRENT_TEST_IS_DISABLED(); - Core ie; - std::stringstream strm; - ExecutableNetwork executableNetwork; - ASSERT_NO_THROW(executableNetwork = ie.LoadNetwork(actualNetwork, deviceName)); - SKIP_IF_NOT_IMPLEMENTED(executableNetwork.Export(strm)); - if (!strm.str().empty() && deviceName.find(CommonTestUtils::DEVICE_FPGA) != std::string::npos) { - SKIP_IF_NOT_IMPLEMENTED(executableNetwork = ie.ImportNetwork(strm)); - } - if (executableNetwork) { - ASSERT_NO_THROW(executableNetwork.CreateInferRequest()); - } -} - TEST_P(IEClassNetworkTestP_VPU, smoke_ImportNetworkNoThrowWithDeviceName) { SKIP_IF_CURRENT_TEST_IS_DISABLED(); Core ie; diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp index 833398f670b..eb6042ad744 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp @@ -115,8 +115,7 @@ namespace BehaviorTestsDefinitions { if ((targetDevice == CommonTestUtils::DEVICE_HDDL) || (targetDevice == CommonTestUtils::DEVICE_GNA)) { ASSERT_EQ(0u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - } else if ((targetDevice == CommonTestUtils::DEVICE_FPGA) || - (targetDevice == CommonTestUtils::DEVICE_KEEMBAY) || + } else if ((targetDevice == CommonTestUtils::DEVICE_KEEMBAY) || (targetDevice == CommonTestUtils::DEVICE_MYRIAD)) { ASSERT_EQ(2u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); } else if (targetDevice == CommonTestUtils::DEVICE_MULTI) { @@ -141,7 +140,7 @@ namespace BehaviorTestsDefinitions { auto execNet = ie->LoadNetwork(cnnNet, targetDevice, config); execNet.CreateInferRequest(); - if ((targetDevice == CommonTestUtils::DEVICE_FPGA) || (targetDevice == CommonTestUtils::DEVICE_MYRIAD) || + if ((targetDevice == CommonTestUtils::DEVICE_MYRIAD) || (targetDevice == CommonTestUtils::DEVICE_KEEMBAY)) { ASSERT_EQ(1u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); } else if (targetDevice == CommonTestUtils::DEVICE_MULTI) { @@ -170,7 +169,7 @@ namespace BehaviorTestsDefinitions { auto execNet = ie->LoadNetwork(cnnNet, targetDevice, config); execNet.CreateInferRequest(); - if ((targetDevice == CommonTestUtils::DEVICE_FPGA) || (targetDevice == CommonTestUtils::DEVICE_MYRIAD) || + if ((targetDevice == CommonTestUtils::DEVICE_MYRIAD) || (targetDevice == CommonTestUtils::DEVICE_KEEMBAY)) { ASSERT_EQ(1u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); ASSERT_EQ(0u, InferenceEngine::ExecutorManager::getInstance()->getIdleCPUStreamsExecutorsNumber()); diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_config.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_config.hpp index d19a78a3393..a1714da07a4 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_config.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_config.hpp @@ -47,7 +47,7 @@ TEST_P(InferConfigTests, canSetExclusiveAsyncRequests) { if ((targetDevice == CommonTestUtils::DEVICE_HDDL) || (targetDevice == CommonTestUtils::DEVICE_GNA)) { ASSERT_EQ(0u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - } else if ((targetDevice == CommonTestUtils::DEVICE_FPGA) || (targetDevice == CommonTestUtils::DEVICE_MYRIAD) || + } else if ((targetDevice == CommonTestUtils::DEVICE_MYRIAD) || (targetDevice == CommonTestUtils::DEVICE_KEEMBAY)) { ASSERT_EQ(2u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); } else if (targetDevice == CommonTestUtils::DEVICE_MULTI) { diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp b/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp index a8089bd3937..21dbeef03b0 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp @@ -11,7 +11,6 @@ const char DEVICE_CPU[] = "CPU"; const char DEVICE_GNA[] = "GNA"; const char DEVICE_GPU[] = "GPU"; const char DEVICE_HDDL[] = "HDDL"; -const char DEVICE_FPGA[] = "FPGA"; const char DEVICE_MYRIAD[] = "MYRIAD"; const char DEVICE_KEEMBAY[] = "VPUX"; const char DEVICE_MULTI[] = "MULTI"; From 4bc98766eded9cf28cc70b5de0ef015afabe868e Mon Sep 17 00:00:00 2001 From: Gabriele Galiero Casay Date: Thu, 13 May 2021 21:15:01 +0200 Subject: [PATCH 54/99] Revise single layer tests for Reduce ops (#5557) * Add serialization single layer tests for reduction operations * Add ReduceSum to the list of trusted ops * Minor changes in single layer tests for reduction ops --- .../serialization/single_layer/reduce_ops.cpp | 177 ++++++++++++++++++ .../single_layer_tests/reduce_ops.cpp | 19 +- .../layer_tests_summary/utils/constants.py | 1 + 3 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 inference-engine/tests/functional/inference_engine/serialization/single_layer/reduce_ops.cpp diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/reduce_ops.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/reduce_ops.cpp new file mode 100644 index 00000000000..8f28fc7f72b --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/reduce_ops.cpp @@ -0,0 +1,177 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "shared_test_classes/single_layer/reduce_ops.hpp" + +using namespace LayerTestsDefinitions; + +namespace { +TEST_P(ReduceOpsLayerTest, Serialize) { + Serialize(); +} + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::U8, + InferenceEngine::Precision::I8, +}; + +const std::vector keepDims = { + true, + false, +}; + +std::vector opTypes = { + CommonTestUtils::OpType::SCALAR, + CommonTestUtils::OpType::VECTOR, +}; + +const std::vector reductionTypes = { + ngraph::helpers::ReductionType::Mean, + ngraph::helpers::ReductionType::Min, + ngraph::helpers::ReductionType::Max, + ngraph::helpers::ReductionType::Sum, + ngraph::helpers::ReductionType::Prod, + ngraph::helpers::ReductionType::L1, + ngraph::helpers::ReductionType::L2, +}; + +const std::vector reductionLogicalTypes = { + ngraph::helpers::ReductionType::LogicalOr, + ngraph::helpers::ReductionType::LogicalAnd +}; + +const std::vector> inputShapesOneAxis = { + std::vector{10, 20, 30, 40}, + std::vector{3, 5, 7, 9}, + std::vector{10}, +}; + +const std::vector> inputShapes = { + std::vector{10, 20, 30, 40}, + std::vector{3, 5, 7, 9}, +}; + +const std::vector> axes = { + {0}, + {1}, + {2}, + {3}, + {0, 1}, + {0, 2}, + {0, 3}, + {1, 2}, + {1, 3}, + {2, 3}, + {0, 1, 2}, + {0, 1, 3}, + {0, 2, 3}, + {1, 2, 3}, + {0, 1, 2, 3}, + {1, -1} +}; + +const auto paramsOneAxis = testing::Combine( + testing::Values(std::vector{0}), + testing::ValuesIn(opTypes), + testing::ValuesIn(keepDims), + testing::ValuesIn(reductionTypes), + testing::Values(netPrecisions[0]), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Layout::ANY), + testing::ValuesIn(inputShapesOneAxis), + testing::Values(CommonTestUtils::DEVICE_CPU) +); + +const auto paramsOneAxisLogical = testing::Combine( + testing::Values(std::vector{0}), + testing::ValuesIn(opTypes), + testing::ValuesIn(keepDims), + testing::ValuesIn(reductionLogicalTypes), + testing::Values(InferenceEngine::Precision::BOOL), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Layout::ANY), + testing::ValuesIn(inputShapesOneAxis), + testing::Values(CommonTestUtils::DEVICE_CPU) +); + +const auto params_Axes = testing::Combine( + testing::ValuesIn(axes), + testing::Values(opTypes[1]), + testing::ValuesIn(keepDims), + testing::Values(reductionTypes[0]), + testing::Values(netPrecisions[0]), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Layout::ANY), + testing::ValuesIn(inputShapes), + testing::Values(CommonTestUtils::DEVICE_CPU) +); + +const auto params_ReductionTypes = testing::Combine( + testing::Values(std::vector{0, 1, 3}), + testing::Values(opTypes[1]), + testing::ValuesIn(keepDims), + testing::ValuesIn(reductionTypes), + testing::ValuesIn(netPrecisions), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Layout::ANY), + testing::Values(std::vector{2, 9, 2, 9}), + testing::Values(CommonTestUtils::DEVICE_CPU) +); + +const auto params_ReductionTypesLogical = testing::Combine( + testing::Values(std::vector{0, 1, 3}), + testing::Values(opTypes[1]), + testing::ValuesIn(keepDims), + testing::ValuesIn(reductionLogicalTypes), + testing::Values(InferenceEngine::Precision::BOOL), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Layout::ANY), + testing::Values(std::vector{2, 9, 2, 9}), + testing::Values(CommonTestUtils::DEVICE_CPU) +); + +INSTANTIATE_TEST_CASE_P( + smoke_ReduceOneAxis_Serialization, + ReduceOpsLayerTest, + paramsOneAxis, + ReduceOpsLayerTest::getTestCaseName +); + +INSTANTIATE_TEST_CASE_P( + smoke_ReduceLogicalOneAxis_Serialization, + ReduceOpsLayerTest, + paramsOneAxisLogical, + ReduceOpsLayerTest::getTestCaseName +); + +INSTANTIATE_TEST_CASE_P( + smoke_ReduceAxes_Serialization, + ReduceOpsLayerTest, + params_Axes, + ReduceOpsLayerTest::getTestCaseName +); + +INSTANTIATE_TEST_CASE_P( + smoke_Reduce_ReductionTypes_Serialization, + ReduceOpsLayerTest, + params_ReductionTypes, + ReduceOpsLayerTest::getTestCaseName +); + +INSTANTIATE_TEST_CASE_P( + smoke_ReduceLogical_ReductionTypes_Serialization, + ReduceOpsLayerTest, + params_ReductionTypesLogical, + ReduceOpsLayerTest::getTestCaseName +); +} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reduce_ops.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reduce_ops.cpp index ad4a24430ac..f5d96aa0d5d 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reduce_ops.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reduce_ops.cpp @@ -12,9 +12,7 @@ using namespace LayerTestsDefinitions; namespace { const std::vector netPrecisions = { InferenceEngine::Precision::FP32, - InferenceEngine::Precision::I32, - InferenceEngine::Precision::U8, - InferenceEngine::Precision::I8, + InferenceEngine::Precision::I32 }; const std::vector keepDims = { @@ -75,9 +73,9 @@ const std::vector reductionLogicalTypes = { const auto paramsOneAxis = testing::Combine( testing::Values(std::vector{0}), testing::ValuesIn(opTypes), - testing::Values(true, false), + testing::ValuesIn(keepDims), testing::ValuesIn(reductionTypes), - testing::Values(InferenceEngine::Precision::FP32), + testing::Values(netPrecisions[0]), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Layout::ANY), @@ -88,7 +86,7 @@ const auto paramsOneAxis = testing::Combine( const auto paramsOneAxisLogical = testing::Combine( testing::Values(std::vector{0}), testing::ValuesIn(opTypes), - testing::Values(true, false), + testing::ValuesIn(keepDims), testing::ValuesIn(reductionLogicalTypes), testing::Values(InferenceEngine::Precision::BOOL), testing::Values(InferenceEngine::Precision::UNSPECIFIED), @@ -103,8 +101,7 @@ const auto params_Precisions = testing::Combine( testing::Values(opTypes[1]), testing::ValuesIn(keepDims), testing::Values(ngraph::helpers::ReductionType::Sum), - testing::Values(InferenceEngine::Precision::FP32, - InferenceEngine::Precision::I32), + testing::ValuesIn(netPrecisions), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Layout::ANY), @@ -117,7 +114,7 @@ const auto params_InputShapes = testing::Combine( testing::Values(opTypes[1]), testing::ValuesIn(keepDims), testing::Values(ngraph::helpers::ReductionType::Mean), - testing::Values(InferenceEngine::Precision::FP32), + testing::Values(netPrecisions[0]), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Layout::ANY), @@ -135,7 +132,7 @@ const auto params_Axes = testing::Combine( testing::Values(opTypes[1]), testing::ValuesIn(keepDims), testing::Values(ngraph::helpers::ReductionType::Mean), - testing::Values(InferenceEngine::Precision::FP32), + testing::Values(netPrecisions[0]), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Layout::ANY), @@ -148,7 +145,7 @@ const auto params_ReductionTypes = testing::Combine( testing::Values(opTypes[1]), testing::ValuesIn(keepDims), testing::ValuesIn(reductionTypes), - testing::Values(InferenceEngine::Precision::FP32), + testing::Values(netPrecisions[0]), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Layout::ANY), diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py index f2d02038c9a..5ad652f24c7 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py @@ -65,6 +65,7 @@ VERIFIED_OP_REFERENCES = [ 'ReduceL1-4', 'ReduceL2-4', 'ReduceMean-1', + 'ReduceSum-1', 'RegionYOLO-1', 'Relu-1', 'ReorgYOLO-2', From 6e6e4b7c3a0c3567dc532006303f2a5e14ee155f Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Thu, 13 May 2021 23:20:53 +0300 Subject: [PATCH 55/99] Added additional check for friendly names (#5586) * Added additional check for friendly names * Fixed Functional tests --- .../cnn_network_ngraph_impl.cpp | 32 ++++++ .../cnn_network_ngraph_impl.hpp | 1 + .../cnn_network/cnn_ngraph_impl_tests.cpp | 106 ++++++++++++++++++ .../convert_ngraph_to_cnn_network_tests.cpp | 8 +- 4 files changed, 140 insertions(+), 7 deletions(-) diff --git a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp index 4681680db3b..62c79ecd3ca 100644 --- a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp +++ b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp @@ -94,6 +94,28 @@ void CNNNetworkNGraphImpl::createDataForResult(const ::ngraph::Output<::ngraph:: } } +void CNNNetworkNGraphImpl::validateFunctionNames() const { + // nGraph function parameters and pre-Results operations should have unique names + std::unordered_set unique_names; + for (const auto& param : _ngraph_function->get_parameters()) { + if (unique_names.count(param->get_friendly_name())) { + IE_THROW() << "Function contains several inputs with one friendly name!"; + } + unique_names.insert(param->get_friendly_name()); + } + for (const auto& result : _ngraph_function->get_results()) { + const auto& parent = result->get_input_node_shared_ptr(0); + auto name = parent->get_friendly_name(); + if (parent->get_output_size() > 1) { + name += "." + std::to_string(result->get_input_source_output(0).get_index()); + } + if (unique_names.count(name) && !ngraph::op::is_parameter(parent)) { + IE_THROW() << "Function contains several inputs and outputs with one friendly name!"; + } + unique_names.insert(name); + } +} + CNNNetworkNGraphImpl::CNNNetworkNGraphImpl( const std::shared_ptr& nGraph, const std::vector& exts) @@ -113,6 +135,8 @@ CNNNetworkNGraphImpl::CNNNetworkNGraphImpl( network.setInputInfo(info); }; + validateFunctionNames(); + reshape(); for (const auto& layer : _ngraph_function->get_parameters()) { std::string outName = layer->get_friendly_name(); @@ -148,6 +172,7 @@ CNNNetworkNGraphImpl::CNNNetworkNGraphImpl(const CNNNetwork& network) { } _ngraph_function = copyFunction(network.getFunction(), false); + validateFunctionNames(); InputsDataMap inputs = network.getInputsInfo(); OutputsDataMap outputs = network.getOutputsInfo(); @@ -231,6 +256,13 @@ StatusCode CNNNetworkNGraphImpl::addOutput(const std::string& layerName, size_t auto result = make_shared<::ngraph::op::Result>(layer->output(outputIndex)); result->set_friendly_name(outputName); _ngraph_function->add_results({result}); + // Check that we cannot add Result to layer with non unique friendly name + try { + validateFunctionNames(); + } catch (...) { + _ngraph_function->remove_result(result); + throw; + } if (_outputData.count(outputName) == 0) { reshape(); diff --git a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.hpp b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.hpp index 9d0bc076dd7..a0300b11fa5 100644 --- a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.hpp +++ b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.hpp @@ -105,6 +105,7 @@ private: */ void reshape(); void reshape(const std::map>& inputShapes); + void validateFunctionNames() const; }; } // namespace details } // namespace InferenceEngine diff --git a/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp b/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp index ac041eb1a35..a75822720ac 100644 --- a/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp @@ -1678,4 +1678,110 @@ TEST(CNNNGraphImplTests, SaveOriginalResultNameForMultiOutputOpOpset6) { ASSERT_NE(outputs.find("text_features"), outputs.end()); } } + +TEST(CNNNGraphImplTests, CheckUniqueNames) { + std::shared_ptr f; + { + auto boxes = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1000, 4}); + boxes->set_friendly_name("boxes"); + auto scores = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1, 1000}); + scores->set_friendly_name("scores"); + auto max_output_boxes_per_class = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10}); + auto iou_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75}); + auto score_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7}); + auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, + ngraph::opset5::NonMaxSuppression::BoxEncodingType::CORNER, true); + + auto result1 = std::make_shared(nms->output(0)); + result1->set_friendly_name("result1"); + auto result2 = std::make_shared(nms->output(1)); + result2->set_friendly_name("result2"); + auto result3 = std::make_shared(nms->output(2)); + result3->set_friendly_name("result3"); + nms->set_friendly_name("nms"); + f = std::make_shared(ngraph::ResultVector{result1, result2, result3}, ngraph::ParameterVector{boxes, scores}); + } + + ASSERT_NO_THROW(InferenceEngine::CNNNetwork{f}); +} + +TEST(CNNNGraphImplTests, CheckNonUniqueParameterName) { + std::shared_ptr f; + { + auto boxes = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1000, 4}); + boxes->set_friendly_name("boxes"); + auto scores = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1, 1000}); + scores->set_friendly_name("boxes"); + auto max_output_boxes_per_class = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10}); + auto iou_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75}); + auto score_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7}); + auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, + ngraph::opset5::NonMaxSuppression::BoxEncodingType::CORNER, true); + + auto result1 = std::make_shared(nms->output(0)); + result1->set_friendly_name("result1"); + auto result2 = std::make_shared(nms->output(1)); + result2->set_friendly_name("result2"); + auto result3 = std::make_shared(nms->output(2)); + result3->set_friendly_name("result3"); + nms->set_friendly_name("nms"); + f = std::make_shared(ngraph::ResultVector{result1, result2, result3}, ngraph::ParameterVector{boxes, scores}); + } + + ASSERT_THROW(InferenceEngine::CNNNetwork{f}, InferenceEngine::Exception); +} + +TEST(CNNNGraphImplTests, CheckNonUniqueResultName) { + std::shared_ptr f; + { + auto boxes = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1000, 4}); + boxes->set_friendly_name("nms.1"); + auto scores = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1, 1000}); + scores->set_friendly_name("scores"); + auto max_output_boxes_per_class = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10}); + auto iou_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75}); + auto score_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7}); + auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, + ngraph::opset5::NonMaxSuppression::BoxEncodingType::CORNER, true); + + auto result1 = std::make_shared(nms->output(0)); + result1->set_friendly_name("result1"); + auto result2 = std::make_shared(nms->output(1)); + result2->set_friendly_name("result2"); + auto result3 = std::make_shared(nms->output(2)); + result3->set_friendly_name("result3"); + nms->set_friendly_name("nms"); + f = std::make_shared(ngraph::ResultVector{result1, result2, result3}, ngraph::ParameterVector{boxes, scores}); + } + + ASSERT_THROW(InferenceEngine::CNNNetwork{f}, InferenceEngine::Exception); +} + +TEST(CNNNGraphImplTests, CheckNonUniqueNewResultName) { + std::shared_ptr f; + { + auto boxes = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1000, 4}); + boxes->set_friendly_name("nms.1"); + auto scores = std::make_shared(ngraph::element::f32, ngraph::Shape{1, 1, 1000}); + scores->set_friendly_name("scores"); + auto max_output_boxes_per_class = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10}); + auto iou_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75}); + auto score_threshold = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7}); + auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, + ngraph::opset5::NonMaxSuppression::BoxEncodingType::CORNER, true); + + auto result1 = std::make_shared(nms->output(0)); + result1->set_friendly_name("result1"); + auto result3 = std::make_shared(nms->output(2)); + result3->set_friendly_name("result3"); + nms->set_friendly_name("nms"); + f = std::make_shared(ngraph::ResultVector{result1, result3}, ngraph::ParameterVector{boxes, scores}); + } + + + CNNNetwork cnnNet; + ASSERT_NO_THROW(cnnNet = InferenceEngine::CNNNetwork{f}); + ASSERT_THROW(cnnNet.addOutput("nms", 1), InferenceEngine::Exception); +} + IE_SUPPRESS_DEPRECATED_END diff --git a/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp b/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp index 5e5944583fc..5a298ed4f41 100644 --- a/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp @@ -355,13 +355,7 @@ TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesNegative) { f = std::make_shared(ngraph::NodeVector{ss, begin, end}, ngraph::ParameterVector{input}); } - InferenceEngine::CNNNetwork nGraphImpl(f); - try { - InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl); - FAIL() << "InferenceEngine::Exception must be thrown"; - } catch(InferenceEngine::Exception & e) { - EXPECT_THAT(e.what(), testing::HasSubstr(std::string("Detected two output operations with the same name:"))); - } + ASSERT_THROW(InferenceEngine::CNNNetwork{f}, InferenceEngine::Exception); } TEST(ConvertFunctionToCNNNetworkTests, NonUniqueNamesParametersNegative) { From 314a1d7de362cc9e7cf6c3ba22b4e172f9dafbdf Mon Sep 17 00:00:00 2001 From: Bartek Szmelczynski Date: Fri, 14 May 2021 06:39:48 +0200 Subject: [PATCH 56/99] Revise gelu (#5327) * add type_prop and backend tests for gelu op * add visitor test for gelu op * add additional type_prop and backend tests and remove gelu from manifest * resolve conflicts * fix indentation and remove unecessary includes * remove gelu from manifests --- ngraph/test/CMakeLists.txt | 1 + ngraph/test/backend/gelu.in.cpp | 130 +++++++++--------- ngraph/test/runtime/ie/unit_test.manifest | 4 - .../runtime/interpreter/unit_test.manifest | 3 - ngraph/test/type_prop/gelu.cpp | 97 +++++++++++++ ngraph/test/visitors/op/gelu.cpp | 27 ++++ 6 files changed, 188 insertions(+), 74 deletions(-) create mode 100644 ngraph/test/type_prop/gelu.cpp create mode 100644 ngraph/test/visitors/op/gelu.cpp diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 835c020e1c4..a18c9feb4b9 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -222,6 +222,7 @@ set(SRC visitors/op/extractimagepatches.cpp visitors/op/fake_quantize.cpp visitors/op/gather.cpp + visitors/op/gelu.cpp visitors/op/grn.cpp visitors/op/group_conv.cpp visitors/op/interpolate.cpp diff --git a/ngraph/test/backend/gelu.in.cpp b/ngraph/test/backend/gelu.in.cpp index 9b4ac215aba..60455d97b48 100644 --- a/ngraph/test/backend/gelu.in.cpp +++ b/ngraph/test/backend/gelu.in.cpp @@ -2,90 +2,86 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include -#include -#include -#include -#include -#include "util/random.hpp" - -// clang-format off -#ifdef ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS -#define DEFAULT_FLOAT_TOLERANCE_BITS ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS -#endif - -#ifdef ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS -#define DEFAULT_DOUBLE_TOLERANCE_BITS ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS -#endif -// clang-format on - #include "gtest/gtest.h" -#include "runtime/backend.hpp" -#include "ngraph/runtime/tensor.hpp" #include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/ndarray.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}, gelu_f32) +NGRAPH_TEST(${BACKEND_NAME}, gelu_erf_mode_inference_f32_8D) { - Shape shape{100000}; - auto A = make_shared(element::f32, shape); - auto f = make_shared(make_shared(A), ParameterVector{A}); + Shape in_shape{8}; + element::Type et = element::f32; - auto backend = runtime::Backend::create("${BACKEND_NAME}"); + auto param = make_shared(et, in_shape); + auto gelu = make_shared(param); + auto f = make_shared(gelu, ParameterVector{param}); - test::Uniform rng(-100.0f, 100.0f); - vector> args; - for (shared_ptr param : f->get_parameters()) - { - auto name = param->get_name(); - vector tensor_val(shape_size(param->get_shape())); - rng.initialize(tensor_val); - args.push_back(tensor_val); - } + vector in_vec{-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0}; + vector out_vec{-0.00012636185, -0.0040495098, -0.04550028, -0.15865529, 0.0, 0.8413447, 1.9544997, 2.9959507}; - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, args[0]); - auto result = backend->create_tensor(element::f32, shape); - - std::transform(args[0].begin(), args[0].end(), args[0].begin(), [](float x) -> float { - return 0.5f * x * (1.0f + erf(x / sqrt(2.0f))); - }); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close(args[0], read_vector(result), .007f, .007f)); + auto test_case = test::TestCase(f); + test_case.add_input(in_shape, in_vec); + test_case.add_expected_output(in_shape, out_vec); + test_case.run_with_tolerance_as_fp(1e-4f); } -NGRAPH_TEST(${BACKEND_NAME}, gelu_f64) +NGRAPH_TEST(${BACKEND_NAME}, gelu_tanh_mode_inference_f32_8D) { - Shape shape{8}; - auto A = make_shared(element::f64, shape); - auto f = make_shared(make_shared(A), ParameterVector{A}); + Shape in_shape{8}; + element::Type et = element::f32; - auto backend = runtime::Backend::create("${BACKEND_NAME}"); + auto param = make_shared(et, in_shape); + auto gelu = make_shared(param, op::GeluApproximationMode::TANH); + auto f = make_shared(gelu, ParameterVector{param}); - // Create some tensors for input/output - auto a = backend->create_tensor(element::f64, shape); - vector input{-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0}; - copy_data(a, input); - auto result = backend->create_tensor(element::f64, shape); + vector in_vec{-4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0}; + vector out_vec{-0.00012636185, -0.0040495098, -0.04550028, -0.15865529, 0.0, 0.8413447, 1.9544997, 2.9959507}; - std::transform(input.begin(), input.end(), input.begin(), [](double x) -> double { - return 0.5 * x * (1.0 + erf(x / sqrt(2.0))); - }); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f(input, read_vector(result))); + auto test_case = test::TestCase(f); + test_case.add_input(in_shape, in_vec); + test_case.add_expected_output(in_shape, out_vec); + test_case.run_with_tolerance_as_fp(1e-3f); +} + +NGRAPH_TEST(${BACKEND_NAME}, gelu_erf_mode_inference_f32_3D) +{ + Shape in_shape{3}; + element::Type et = element::f32; + + auto param = make_shared(et, in_shape); + auto gelu = make_shared(param); + auto f = make_shared(gelu, ParameterVector{param}); + + vector in_vec{-0.5, 0.1, 0.4}; + vector out_vec{-0.15426877, 0.05398279, 0.2621686}; + + auto test_case = test::TestCase(f); + test_case.add_input(in_shape, in_vec); + test_case.add_expected_output(in_shape, out_vec); + test_case.run_with_tolerance_as_fp(1e-4f); +} + +NGRAPH_TEST(${BACKEND_NAME}, gelu_tanh_mode_inference_f32_3D) +{ + Shape in_shape{3}; + element::Type et = element::f32; + + auto param = make_shared(et, in_shape); + auto gelu = make_shared(param, op::GeluApproximationMode::TANH); + auto f = make_shared(gelu, ParameterVector{param}); + + vector in_vec{-0.5, 0.1, 0.4}; + vector out_vec{-0.15428599, 0.053982753, 0.262161165}; + + auto test_case = test::TestCase(f); + test_case.add_input(in_shape, in_vec); + test_case.add_expected_output(in_shape, out_vec); + test_case.run_with_tolerance_as_fp(1e-4f); } diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index 9e8bb87ca58..12dfc479b3a 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -940,10 +940,6 @@ topk_max_sort_index topk_min_sort_index topk_1d_i32_max_all topk_int64 -gelu_f32 -gelu_f64 -gelu_backprop_factor_f32 -gelu_backprop_factor_f64 backwards_abs backwards_acos diff --git a/ngraph/test/runtime/interpreter/unit_test.manifest b/ngraph/test/runtime/interpreter/unit_test.manifest index 7d7d209c50d..16412a94291 100644 --- a/ngraph/test/runtime/interpreter/unit_test.manifest +++ b/ngraph/test/runtime/interpreter/unit_test.manifest @@ -55,9 +55,6 @@ INTERPRETER.min_to_scalar_int8 INTERPRETER.max_trivial_int8 INTERPRETER.max_to_scalar_int8 INTERPRETER.max_3d_to_scalar_double -INTERPRETER.gelu_f64 -INTERPRETER.gelu_backprop_factor_f64 -INTERPRETER.backwards_gelu_f64 INTERPRETER.gather_4d_indices_axis_0_uint8 INTERPRETER.gather_axis_0_int8 INTERPRETER.gather_axis_0_int16 diff --git a/ngraph/test/type_prop/gelu.cpp b/ngraph/test/type_prop/gelu.cpp new file mode 100644 index 00000000000..28cf820616c --- /dev/null +++ b/ngraph/test/type_prop/gelu.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "util/type_prop.hpp" + +using namespace std; +using namespace ngraph; + +TEST(type_prop, gelu_default_mode_inference_f32) +{ + auto param = make_shared(element::f32, Shape{1, 32, 32}); + auto gelu = make_shared(param); + + ASSERT_EQ(gelu->get_element_type(), element::f32); + ASSERT_EQ(gelu->get_shape(), (Shape{1, 32, 32})); + ASSERT_EQ(gelu->get_approximation_mode(), op::GeluApproximationMode::ERF); +} + +TEST(type_prop, gelu_default_mode_inference_f16) +{ + auto param = make_shared(element::f16, Shape{1, 32, 32}); + auto gelu = make_shared(param); + + ASSERT_EQ(gelu->get_element_type(), element::f16); + ASSERT_EQ(gelu->get_shape(), (Shape{1, 32, 32})); + ASSERT_EQ(gelu->get_approximation_mode(), op::GeluApproximationMode::ERF); +} + +TEST(type_prop, gelu_tanh_mode_inference_f32) +{ + auto param = make_shared(element::f32, Shape{1, 32, 32}); + auto gelu = make_shared(param, op::GeluApproximationMode::TANH); + + ASSERT_EQ(gelu->get_element_type(), element::f32); + ASSERT_EQ(gelu->get_shape(), (Shape{1, 32, 32})); + ASSERT_EQ(gelu->get_approximation_mode(), op::GeluApproximationMode::TANH); +} + +TEST(type_prop, gelu_tanh_mode_inference_f16) +{ + auto param = make_shared(element::f16, Shape{1, 32, 32}); + auto gelu = make_shared(param, op::GeluApproximationMode::TANH); + + ASSERT_EQ(gelu->get_element_type(), element::f16); + ASSERT_EQ(gelu->get_shape(), (Shape{1, 32, 32})); + ASSERT_EQ(gelu->get_approximation_mode(), op::GeluApproximationMode::TANH); +} + +TEST(type_prop, gelu_incompatible_input_type_boolean) +{ + auto param = make_shared(element::boolean, Shape{1, 32, 32}); + ASSERT_THROW(std::make_shared(param), ngraph::NodeValidationFailure); +} + +TEST(type_prop, gelu_incompatible_input_type_u16) +{ + auto param = make_shared(element::u16, Shape{1, 32, 32}); + ASSERT_THROW(std::make_shared(param), ngraph::NodeValidationFailure); +} + +TEST(type_prop, gelu_incompatible_input_type_i32) +{ + auto param = make_shared(element::i32, Shape{1, 32, 32}); + ASSERT_THROW(std::make_shared(param), ngraph::NodeValidationFailure); +} + +TEST(type_prop, gelu_incompatible_input_type_i16) +{ + auto param = make_shared(element::i16, Shape{1, 32, 32}); + ASSERT_THROW(std::make_shared(param), ngraph::NodeValidationFailure); +} + +TEST(type_prop, gelu_dynamic_rank_input_shape_2D) +{ + const PartialShape param_shape{Dimension::dynamic(), 10}; + const auto param = std::make_shared(element::f32, param_shape); + const auto op = std::make_shared(param); + ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{Dimension(), 10})); +} + +TEST(type_prop, gelu_dynamic_rank_input_shape_3D) +{ + const PartialShape param_shape{100, Dimension::dynamic(), 58}; + const auto param = std::make_shared(element::f32, param_shape); + const auto op = std::make_shared(param); + ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{100, Dimension(), 58})); +} + +TEST(type_prop, gelu_dynamic_rank_input_shape_full) +{ + const auto param = std::make_shared(element::f32, PartialShape::dynamic()); + const auto op = std::make_shared(param); + ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape::dynamic())); +} diff --git a/ngraph/test/visitors/op/gelu.cpp b/ngraph/test/visitors/op/gelu.cpp new file mode 100644 index 00000000000..eff6c43f409 --- /dev/null +++ b/ngraph/test/visitors/op/gelu.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" + +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset7.hpp" + +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; + +TEST(attributes, gelu_op) +{ + NodeBuilder::get_ops().register_factory(); + const auto data_input = make_shared(element::f32, Shape{1, 2, 3}); + const auto approximation_mode = op::GeluApproximationMode::ERF; + const auto gelu = make_shared(data_input, approximation_mode); + NodeBuilder builder(gelu); + auto g_gelu = as_type_ptr(builder.create()); + + EXPECT_EQ(g_gelu->get_approximation_mode(), gelu->get_approximation_mode()); +} From 61e9d020d46258544880566b1f49008fd1a31c2c Mon Sep 17 00:00:00 2001 From: Bartosz Lesniewski Date: Fri, 14 May 2021 06:44:48 +0200 Subject: [PATCH 57/99] Revise Unsqueeze op - tests (#5579) * Add visitor test, separate backend test from common fused op file * Add SSLT, separate empty axes squeeze case in SLT * Add unsqueeze to trusted op list * removing trailing whitespaces * Add missing newlines at file end * Review comments - actually running backend tests, fixed typo in visitor test --- .../serialization/single_layer/unsqueeze.cpp | 46 ++++++++++++++++++ .../single_layer_tests/squeeze_unsqueeze.cpp | 33 ++++++++++--- .../single_layer_tests/squeeze_unsqueeze.cpp | 33 ++++++++++--- .../src/single_layer/squeeze_unsqueeze.cpp | 13 ++--- .../layer_tests_summary/utils/constants.py | 3 +- ngraph/test/CMakeLists.txt | 2 + ngraph/test/backend/fused_op.in.cpp | 15 ------ ngraph/test/backend/unsqueeze.in.cpp | 47 +++++++++++++++++++ ngraph/test/visitors/op/unsqueeze.cpp | 29 ++++++++++++ 9 files changed, 187 insertions(+), 34 deletions(-) create mode 100644 inference-engine/tests/functional/inference_engine/serialization/single_layer/unsqueeze.cpp create mode 100644 ngraph/test/backend/unsqueeze.in.cpp create mode 100644 ngraph/test/visitors/op/unsqueeze.cpp diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/unsqueeze.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/unsqueeze.cpp new file mode 100644 index 00000000000..2e26a70d627 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/unsqueeze.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "shared_test_classes/single_layer/squeeze_unsqueeze.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +namespace { +TEST_P(SqueezeUnsqueezeLayerTest, Serialize) { + Serialize(); +} + +std::map, std::vector>> axesVectors = { + {{1, 1, 1, 1}, {{-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {0, 1, 2}, {0, 2, 3}, {1, 2, 3}, {0, 1, 2, 3}}}, + {{1, 2, 3, 4}, {{0}}}, + {{2, 1, 3, 4}, {{1}}}, + {{1}, {{-1}, {0}}}, + {{1, 2}, {{0}}}, + {{2, 1}, {{1}, {-1}}}, +}; + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::U32}; + +const std::vector opTypes = { + ngraph::helpers::SqueezeOpType::UNSQUEEZE}; + +INSTANTIATE_TEST_CASE_P(smoke_Squeeze_Basic, SqueezeUnsqueezeLayerTest, + ::testing::Combine( + ::testing::ValuesIn(CommonTestUtils::combineParams(axesVectors)), + ::testing::ValuesIn(opTypes), + ::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(CommonTestUtils::DEVICE_CPU)), + SqueezeUnsqueezeLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp index 1b1944f44f0..a5a8f35a350 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp @@ -11,12 +11,21 @@ using namespace LayerTestsDefinitions; namespace { std::map, std::vector>> axesVectors = { - {{1, 1, 1, 1}, {{}, {-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {0, 1, 2}, {0, 2, 3}, {1, 2, 3}, {0, 1, 2, 3}}}, - {{1, 2, 3, 4}, {{}, {0}}}, - {{2, 1, 3, 4}, {{}, {1}}}, - {{1}, {{}, {-1}, {0}}}, - {{1, 2}, {{}, {0}}}, - {{2, 1}, {{}, {1}, {-1}}}, + {{1, 1, 1, 1}, {{-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {0, 1, 2}, {0, 2, 3}, {1, 2, 3}, {0, 1, 2, 3}}}, + {{1, 2, 3, 4}, {{0}}}, + {{2, 1, 3, 4}, {{1}}}, + {{1}, {{-1}, {0}}}, + {{1, 2}, {{0}}}, + {{2, 1}, {{1}, {-1}}}, +}; + +std::map, std::vector>> emptyAxesVectors = { + {{1, 1, 1, 1}, {{}}}, + {{1, 2, 3, 4}, {{}}}, + {{2, 1, 3, 4}, {{}}}, + {{1}, {{}}}, + {{1, 2}, {{}}}, + {{2, 1}, {{}}}, }; const std::vector netPrecisions = { @@ -40,4 +49,16 @@ INSTANTIATE_TEST_CASE_P(smoke_Basic, SqueezeUnsqueezeLayerTest, ::testing::Values(InferenceEngine::Layout::ANY), ::testing::Values(CommonTestUtils::DEVICE_CPU)), SqueezeUnsqueezeLayerTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_Basic_emptyAxes, SqueezeUnsqueezeLayerTest, + ::testing::Combine( + ::testing::ValuesIn(CommonTestUtils::combineParams(emptyAxesVectors)), + ::testing::Values(ngraph::helpers::SqueezeOpType::SQUEEZE), + ::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(CommonTestUtils::DEVICE_CPU)), + SqueezeUnsqueezeLayerTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp index 365282fc772..ca5b6ece34a 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/squeeze_unsqueeze.cpp @@ -11,12 +11,21 @@ using namespace LayerTestsDefinitions; namespace { std::map, std::vector>> axesVectors = { - {{1, 1, 1, 1}, {{}, {-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}}}, - {{1, 2, 3, 4}, {{}, {0}}}, - {{2, 1, 3, 4}, {{}, {1}}}, - {{1}, {{}, {-1}, {0}}}, - {{1, 2}, {{}, {0}}}, - {{2, 1}, {{}, {1}, {-1}}}, + {{1, 1, 1, 1}, {{-1}, {0}, {1}, {2}, {3}, {0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {0, 1, 2}, {0, 2, 3}, {1, 2, 3}, {0, 1, 2, 3}}}, + {{1, 2, 3, 4}, {{0}}}, + {{2, 1, 3, 4}, {{1}}}, + {{1}, {{-1}, {0}}}, + {{1, 2}, {{0}}}, + {{2, 1}, {{1}, {-1}}}, +}; + +std::map, std::vector>> emptyAxesVectors = { + {{1, 1, 1, 1}, {{}}}, + {{1, 2, 3, 4}, {{}}}, + {{2, 1, 3, 4}, {{}}}, + {{1}, {{}}}, + {{1, 2}, {{}}}, + {{2, 1}, {{}}}, }; const std::vector netPrecisions = { @@ -40,4 +49,16 @@ INSTANTIATE_TEST_CASE_P(smoke_Basic, SqueezeUnsqueezeLayerTest, ::testing::Values(InferenceEngine::Layout::ANY), ::testing::Values(CommonTestUtils::DEVICE_GPU)), SqueezeUnsqueezeLayerTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_Basic_emptyAxes, SqueezeUnsqueezeLayerTest, + ::testing::Combine( + ::testing::ValuesIn(CommonTestUtils::combineParams(emptyAxesVectors)), + ::testing::Values(ngraph::helpers::SqueezeOpType::SQUEEZE), + ::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(CommonTestUtils::DEVICE_GPU)), + SqueezeUnsqueezeLayerTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/squeeze_unsqueeze.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/squeeze_unsqueeze.cpp index d5108a05515..ca78f3805ef 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/squeeze_unsqueeze.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/squeeze_unsqueeze.cpp @@ -39,14 +39,15 @@ void SqueezeUnsqueezeLayerTest::SetUp() { auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); auto params = ngraph::builder::makeParams(ngPrc, {inputShapes}); - std::shared_ptr squeeze; + std::shared_ptr op; - if (!axesVector.empty()) { - squeeze = ngraph::builder::makeSqueezeUnsqueeze(params.front(), ngraph::element::i64, axesVector, opType); + if (axesVector.empty() && opType == ngraph::helpers::SqueezeOpType::SQUEEZE) { + op = std::make_shared(params.front()); } else { - squeeze = std::make_shared(params.front()); + op = ngraph::builder::makeSqueezeUnsqueeze(params.front(), ngraph::element::i64, axesVector, opType); } - const ngraph::ResultVector results{std::make_shared(squeeze)}; + + const ngraph::ResultVector results{std::make_shared(op)}; function = std::make_shared(results, params, "Squeeze"); } -} // namespace LayerTestsDefinitions \ No newline at end of file +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py index 5ad652f24c7..20442899b87 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py @@ -85,5 +85,6 @@ VERIFIED_OP_REFERENCES = [ 'Tile-1', 'TopK-1', 'TopK-3', - 'Transpose-1' + 'Transpose-1', + 'Unsqueeze-1' ] diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index a18c9feb4b9..6848436253f 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -268,6 +268,7 @@ set(SRC visitors/op/tanh.cpp visitors/op/topk.cpp visitors/op/transpose.cpp + visitors/op/unsqueeze.cpp uint4.cpp util.cpp ) @@ -425,6 +426,7 @@ set(MULTI_TEST_SRC backend/topk.in.cpp backend/transpose.in.cpp backend/unhandled_op.in.cpp + backend/unsqueeze.in.cpp backend/validate_call.in.cpp backend/zero_sized.in.cpp ) diff --git a/ngraph/test/backend/fused_op.in.cpp b/ngraph/test/backend/fused_op.in.cpp index 567b590b24e..74117a7fb9f 100644 --- a/ngraph/test/backend/fused_op.in.cpp +++ b/ngraph/test/backend/fused_op.in.cpp @@ -619,21 +619,6 @@ NGRAPH_TEST(${BACKEND_NAME}, DISABLED_grn_2d_with_bias) test_case.run(); } -NGRAPH_TEST(${BACKEND_NAME}, unsqueeze) -{ - auto data_node = make_shared(element::f32, Shape{4, 2}); - auto axes_node = - make_shared(element::i64, Shape{2}, vector{1, 2}); - auto squeeze = make_shared(data_node, axes_node); - - auto function = make_shared(NodeVector{squeeze}, ParameterVector{data_node}); - auto test_case = test::TestCase(function); - - auto data = vector{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f}; - test_case.add_input(data); - test_case.add_expected_output(Shape{4, 1, 1, 2}, data); -} - NGRAPH_TEST(${BACKEND_NAME}, shuffle_channels_simple) { const auto data = make_shared(element::i32, Shape{1, 15, 2, 2}); diff --git a/ngraph/test/backend/unsqueeze.in.cpp b/ngraph/test/backend/unsqueeze.in.cpp new file mode 100644 index 00000000000..893edb459ea --- /dev/null +++ b/ngraph/test/backend/unsqueeze.in.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "util/engine/test_engines.hpp" +#include "util/test_case.hpp" +#include "util/test_control.hpp" + +using namespace std; +using namespace ngraph; + +static string s_manifest = "${MANIFEST}"; +using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); + +NGRAPH_TEST(${BACKEND_NAME}, unsqueeze) +{ + auto data_node = make_shared(element::f32, Shape{4, 2}); + auto axes_node = + make_shared(element::i64, Shape{2}, vector{1, 2}); + auto squeeze = make_shared(data_node, axes_node); + + auto function = make_shared(NodeVector{squeeze}, ParameterVector{data_node}); + auto test_case = test::TestCase(function); + + auto data = vector{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f}; + test_case.add_input(data); + test_case.add_expected_output(Shape{4, 1, 1, 2}, data); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, unsqueeze_negative_axis) +{ + auto data_node = make_shared(element::f32, Shape{4, 2}); + auto axes_node = + make_shared(element::i64, Shape{2}, vector{1, -1}); + auto squeeze = make_shared(data_node, axes_node); + + auto function = make_shared(NodeVector{squeeze}, ParameterVector{data_node}); + auto test_case = test::TestCase(function); + + auto data = vector{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f}; + test_case.add_input(data); + test_case.add_expected_output(Shape{4, 1, 2, 1}, data); + test_case.run(); +} diff --git a/ngraph/test/visitors/op/unsqueeze.cpp b/ngraph/test/visitors/op/unsqueeze.cpp new file mode 100644 index 00000000000..d0fbf499486 --- /dev/null +++ b/ngraph/test/visitors/op/unsqueeze.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" + +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset1.hpp" + +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; + +TEST(attributes, unsqueeze_op) +{ + using namespace opset1; + + auto param = make_shared(element::f32, Shape{4, 1, 4, 1, 8}); + auto axes = make_shared(element::u64, Shape{2}, vector{1, 2}); + auto op = make_shared(param, axes); + + NodeBuilder builder(op); + const auto expected_attr_count = 0; + + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); +} From 621e36ee7937b22806926ef78013a964b597afd6 Mon Sep 17 00:00:00 2001 From: Alexandra Sidorova Date: Fri, 14 May 2021 07:52:05 +0300 Subject: [PATCH 58/99] Added MVN fusion for case with constants inside (#4961) --- .../common_optimizations/mvn_fusion.hpp | 32 ++++- .../common_optimizations/mvn_fusion.cpp | 116 +++++++++++++++++- .../transformations/mvn_fusion_test.cpp | 46 +++++++ 3 files changed, 189 insertions(+), 5 deletions(-) diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/mvn_fusion.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/mvn_fusion.hpp index 3de28fe67f9..6a25a3f00f7 100644 --- a/inference-engine/src/transformations/include/transformations/common_optimizations/mvn_fusion.hpp +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/mvn_fusion.hpp @@ -16,7 +16,9 @@ namespace ngraph { namespace pass { - class TRANSFORMATIONS_API MVNFusion; +class TRANSFORMATIONS_API MVNFusion; +class TRANSFORMATIONS_API MVNFusionWithoutConstants; +class TRANSFORMATIONS_API MVNFusionWithConstantsInside; } // namespace pass } // namespace ngraph @@ -26,8 +28,32 @@ namespace pass { * @brief MVNFusion transformation replaces group of * operations: (x - ReduceMean(x, axes)) / (Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2)) + eps) to MVN op. */ -class ngraph::pass::MVNFusion : public ngraph::pass::MatcherPass { +class ngraph::pass::MVNFusionWithoutConstants : public ngraph::pass::MatcherPass { public: NGRAPH_RTTI_DECLARATION; - MVNFusion(); + MVNFusionWithoutConstants(); +}; + +/** + * @ingroup ie_transformation_common_api + * @brief MVNFusion transformation replaces group of + * operations: gamma * (x - ReduceMean(x, axes)) / (Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2)) + eps) - beta to MVN op. + */ +class ngraph::pass::MVNFusionWithConstantsInside : public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + MVNFusionWithConstantsInside(); +}; + +/** + * @ingroup ie_transformation_common_api + * @brief MVNFusion transformation replaces various sub-graphs with a MVN op. + */ +class ngraph::pass::MVNFusion: public ngraph::pass::GraphRewrite { +public: + NGRAPH_RTTI_DECLARATION; + MVNFusion() { + add_matcher(); + add_matcher(); + } }; diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/mvn_fusion.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/mvn_fusion.cpp index 9ef143a614e..bb0a97c03f0 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/mvn_fusion.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/mvn_fusion.cpp @@ -27,8 +27,10 @@ std::function)> value_is_equal_to(const std::v }; } -ngraph::pass::MVNFusion::MVNFusion() { - MATCHER_SCOPE(MVNFusion); +NGRAPH_RTTI_DEFINITION(ngraph::pass::MVNFusionWithoutConstants, "MVNFusionWithoutConstants", 0); + +ngraph::pass::MVNFusionWithoutConstants::MVNFusionWithoutConstants() { + MATCHER_SCOPE(MVNFusionWithoutConstants); // Detect MVN decomposition pattern: // (x - ReduceMean(x, axes)) / (Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2)) + eps) auto x = pattern::any_input(); @@ -188,3 +190,113 @@ ngraph::pass::MVNFusion::MVNFusion() { auto m = std::make_shared(powerMulOrDiv, matcher_name); register_matcher(m, matcher_pass_callback); } + +NGRAPH_RTTI_DEFINITION(ngraph::pass::MVNFusionWithConstantsInside, "MVNFusionWithConstantsInside", 0); + +ngraph::pass::MVNFusionWithConstantsInside::MVNFusionWithConstantsInside() { + MATCHER_SCOPE(MVNFusionWithConstantsInside); + // Detect MVN decomposition pattern: + // (x - ReduceMean(x, axes)) * gamma / (Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2)) + eps) - beta + auto x = pattern::any_input(); + + // (x - ReduceMean(x, axes))^2 + // `------mean1-------' + auto mean1_axes = pattern::wrap_type(); + auto mean1 = pattern::wrap_type({ x, mean1_axes }); + + // (x - ReduceMean(x, axes))^2 + // `-squared_difference------' + auto squared_difference = pattern::wrap_type({ x, mean1 }); + + // 1 / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) + // `---mean2--------------------------------' + auto mean2_axes = pattern::wrap_type(); + auto mean2 = pattern::wrap_type({ squared_difference, mean2_axes }); + + // 1 / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) + // `------------------------------------------add--' + auto eps = pattern::wrap_type(); + auto add_eps = pattern::wrap_type({ mean2, eps }); + + // 1 / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) + // `-power-------------------------------------------------' + auto const_0_5 = pattern::wrap_type(value_is_equal_to({-0.5})); + auto power = pattern::wrap_type({ add_eps, const_0_5 }); + + // gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) + // `---mul1----------------------------------------------------' + auto gamma = pattern::wrap_type(); + auto mul1 = pattern::wrap_type({ power, gamma }); + + // x * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) + // `---mul2--------------------------------------------------------' + auto mul2 = pattern::wrap_type({ x, mul1 }); + + // ReduceMean(x, axes) * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - beta + // `-------------------mul3----------------------------------------------------------' + auto mul3 = pattern::wrap_type({ mul1, mean1 }); + + // beta - ReduceMean(x, axes) * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) + // `---sub-----------------------------------------------------------------------------------' + auto beta = pattern::wrap_type(); + auto sub = pattern::wrap_type({ beta, mul3 }); + + // Final Add + // x * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) + + // beta - ReduceMean(x, axes) * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) = + // gamma * (x - ReduceMean(x, axes)) / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - beta + auto add = pattern::wrap_type({ mul2, sub }); + + ngraph::matcher_pass_callback matcher_pass_callback = [=](ngraph::pattern::Matcher& m) { + auto& pattern_to_output = m.get_pattern_value_map(); + auto x_output = pattern_to_output.at(x); + + auto const_0_5_node = std::dynamic_pointer_cast(pattern_to_output.at(const_0_5).get_node_shared_ptr()); + if (!const_0_5_node) { + return false; + } + + auto const_gamma_node = std::dynamic_pointer_cast(pattern_to_output.at(gamma).get_node_shared_ptr()); + auto const_beta_node = std::dynamic_pointer_cast(pattern_to_output.at(beta).get_node_shared_ptr()); + auto const_eps_node = std::dynamic_pointer_cast(pattern_to_output.at(eps).get_node_shared_ptr()); + float eps_value; + + bool valid_constant_values = op::util::has_constant_value(const_0_5_node, -0.5) && op::util::get_single_value(const_eps_node, eps_value); + if (!valid_constant_values) { + return false; + } + + auto axes_1_node = std::dynamic_pointer_cast(pattern_to_output.at(mean1_axes).get_node_shared_ptr()); + auto axes_2_node = std::dynamic_pointer_cast(pattern_to_output.at(mean2_axes).get_node_shared_ptr()); + if (!axes_1_node || !axes_2_node) { + return false; + } + + auto axes_1_value = axes_1_node->cast_vector(); + auto axes_2_value = axes_2_node->cast_vector(); + if (axes_1_value != axes_2_value) { + return false; + } + + auto mvn = std::make_shared(x_output, axes_1_node, true, eps_value, op::MVNEpsMode::INSIDE_SQRT); + auto mul_gamma = std::make_shared(mvn, const_gamma_node); + auto add_beta = std::make_shared(mul_gamma, const_beta_node); + + ngraph::copy_runtime_info({ pattern_to_output.at(mean1).get_node_shared_ptr(), + pattern_to_output.at(squared_difference).get_node_shared_ptr(), + pattern_to_output.at(add_eps).get_node_shared_ptr(), + pattern_to_output.at(power).get_node_shared_ptr(), + pattern_to_output.at(mul1).get_node_shared_ptr(), + pattern_to_output.at(mul2).get_node_shared_ptr(), + pattern_to_output.at(mul3).get_node_shared_ptr(), + pattern_to_output.at(sub).get_node_shared_ptr(), + pattern_to_output.at(add).get_node_shared_ptr() }, + { mvn, const_gamma_node, mul_gamma, const_beta_node, add_beta }); + add_beta->set_friendly_name(m.get_match_root()->get_friendly_name()); + ngraph::replace_node(m.get_match_root(), add_beta); + return true; + }; + + auto m = std::make_shared(add, matcher_name); + register_matcher(m, matcher_pass_callback); +} diff --git a/inference-engine/tests/functional/inference_engine/transformations/mvn_fusion_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/mvn_fusion_test.cpp index 21b2b695454..e45258a63e6 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/mvn_fusion_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/mvn_fusion_test.cpp @@ -419,3 +419,49 @@ TEST(TransformationTests, MVNFusionTestAltDivInsideSqrt) { auto res = compare_functions(f, f_ref); ASSERT_TRUE(res.first) << res.second; } + +TEST(TransformationTests, MVNFusionTestWithParametersInside) { + std::shared_ptr f(nullptr), f_ref(nullptr); + { + auto input = std::make_shared(ngraph::element::f32, ngraph::Shape{ 1, 3, 224 }); + auto mean1_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 1 }, { 2 }); + auto mean1 = std::make_shared(input, mean1_axes, true); + auto squared_difference = std::make_shared(input, mean1); + auto mean2_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 1 }, { 2 }); + auto mean2 = std::make_shared(squared_difference, mean2_axes, true); + auto eps = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1e-9 }); + auto add_eps = std::make_shared(mean2, eps); + auto const_0_5 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { -0.5 }); + auto power_sqrt = std::make_shared(add_eps, const_0_5); + auto gamma = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1 }); + auto mul_gamma = std::make_shared(power_sqrt, gamma); + auto mul1 = std::make_shared(input, mul_gamma); + auto mul2 = std::make_shared(mul_gamma, mean1); + auto beta = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { -1 }); + auto sub = std::make_shared(beta, mul2); + auto add = std::make_shared(mul1, sub); + + f = std::make_shared(ngraph::NodeVector{ add }, ngraph::ParameterVector{ input }); + + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto input = std::make_shared(ngraph::element::f32, ngraph::Shape{ 1, 3, 224 }); + auto axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 1 }, { 2 }); + auto mvn = std::make_shared(input, axes, true, 1e-9, ngraph::op::MVNEpsMode::INSIDE_SQRT); + auto gamma = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1 }); + auto mul_gamma = std::make_shared(mvn, gamma); + auto beta = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { -1 }); + auto add = std::make_shared(mul_gamma, beta); + + f_ref = std::make_shared(ngraph::NodeVector{ add }, ngraph::ParameterVector{ input }); + } + + auto res = compare_functions(f, f_ref); + ASSERT_TRUE(res.first) << res.second; +} From 75fa5057e19b7becc714b8a628c0187d30cd2443 Mon Sep 17 00:00:00 2001 From: Maksim Kutakov Date: Fri, 14 May 2021 10:15:42 +0300 Subject: [PATCH 59/99] [CPU] Disable zp fusing for 3d dw conv (#5563) --- .../src/mkldnn_plugin/mkldnn_graph_optimizer.cpp | 12 +++++++++++- .../src/mkldnn_plugin/nodes/mkldnn_conv_node.h | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp index f773507b657..ea60902ae02 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp @@ -414,7 +414,17 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndZeroPoints(MKLDNNGraph &graph) { auto& graphNodes = graph.GetNodes(); auto isSutableConvNode = [](MKLDNNNodePtr node) { - return node->getType() == Convolution; + bool retVal = false; + if (node->getType() == Convolution) { + if (auto convNode = std::dynamic_pointer_cast(node)) { + auto ndims = convNode->getParentEdgeAt(0)->getDims().ndims(); + // int8 depthwise convolution does not support fusing zero points in 3D case + if (implication(convNode->isDepthWise(), ndims == 4)) { + retVal = true; + } + } + } + return retVal; }; auto initializeInputZeroPoints = [](MKLDNNNodePtr node, MKLDNNNodePtr parent0, MKLDNNNodePtr parent1) { diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h index 1cdc0065c4c..a0a400dc008 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h @@ -50,6 +50,9 @@ public: const std::vector &getPaddingR() { return paddingR; } bool canFuse(const MKLDNNNodePtr& node) const override; + bool isDepthWise() const { + return isGrouped && 1 == groupOC && 1 == groupIC; + } protected: InferenceEngine::Precision fusedEltwisePrecision(const MKLDNNNodePtr& fusingNode) const; From 5fa899a39e1fd11061e459613a1cd386154445c1 Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Fri, 14 May 2021 10:31:36 +0300 Subject: [PATCH 60/99] [nG] Gather-7 update for negative batch_dims (#5522) * corrected negative batch_dims normalization, some improvements in dynamism for Gather_7 * corrected transformation * added batch_dims and axis normalization for reference * updated INTERPRETER backend tests; replaced sizet_t -> int64_t in Gather evaluate * returned back size_t in reference * made Gather-1 source compatible with previous ngraph library versions * added unittest for v7->v1, with nonzero batch_dims transformation should not be executed * fix axis validation error message * fix batch_dims gettter * fixed v7->v1 unittest for nonzero batch_dims --- docs/ops/movement/Gather_7.md | 7 +- .../algebraic_simplification.cpp | 9 +- .../convert_gather_v7_to_gather_v1.cpp | 8 +- .../convert_gather_v7_to_gather_v1_test.cpp | 23 +++ ngraph/core/include/ngraph/op/gather.hpp | 3 + .../include/ngraph/op/util/gather_base.hpp | 4 +- ngraph/core/src/op/gather.cpp | 15 ++ ngraph/core/src/op/util/gather_base.cpp | 159 ++++++++---------- ngraph/test/backend/gather.in.cpp | 29 +++- ngraph/test/runtime/ie/unit_test.manifest | 1 + ngraph/test/type_prop/gather.cpp | 84 +++++---- 11 files changed, 197 insertions(+), 145 deletions(-) diff --git a/docs/ops/movement/Gather_7.md b/docs/ops/movement/Gather_7.md index d0ca451fee2..4b421790c77 100644 --- a/docs/ops/movement/Gather_7.md +++ b/docs/ops/movement/Gather_7.md @@ -22,7 +22,7 @@ the number of batch dimensions. `N` and `M` are numbers of dimensions of `data` representing the batches, and *Gather* starts to gather from the `b` dimension. It requires the first `b` dimensions in `data` and `indices` tensors to be equal. If `batch_dims` is less than zero, normalized value is used `batch_dims = indices.rank + batch_dims`. - * **Range of values**: `[-min(data.rank, indices.rank); min(data.rank, indices.rank))` and `batch_dims' <= axis'`. + * **Range of values**: `[-min(data.rank, indices.rank); min(data.rank, indices.rank)]` and `batch_dims' <= axis'`. Where `batch_dims'` and `axis'` stand for normalized `batch_dims` and `axis` values. * **Type**: *T_AXIS* * **Default value**: 0 @@ -136,8 +136,9 @@ output_shape = (2, 3) * **1**: `data` tensor of type *T* with arbitrary data. **Required**. -* **2**: `indices` tensor of type *T_IND* with indices to gather. The values for indices are in the range `[0, data[axis] - 1]`. -**Required**. +* **2**: `indices` tensor of type *T_IND* with indices to gather. 0D tensor (scalar) for indices is also allowed. + The values for indices are in the range `[0, data[axis] - 1]`. + **Required**. * **3**: Scalar or 1D tensor `axis` of *T_AXIS* type is a dimension index to gather data from. For example, *axis* equal to 1 means that gathering is performed over the first dimension. Negative `axis` means reverse indexing and diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/algebraic_simplification.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/algebraic_simplification.cpp index 4800121b0dd..1bb4243f8c3 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/algebraic_simplification.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/algebraic_simplification.cpp @@ -37,12 +37,11 @@ static bool simplify_gather(std::shared_ptr node) { return false; } - - if (!gather->is_axis_set()) { + auto axis = gather->get_axis(); + if (axis == opset3::Gather::AXIS_NOT_SET_VALUE) { NGRAPH_DEBUG << "axis value not set"; return false; } - auto axis = gather->get_axis(); // case_1 : if the input tensor is of shape (4, 1, 4) // and axis = 1, then the gather would be simply @@ -85,12 +84,12 @@ static bool simplify_gather_shapeof(shared_ptr node) { } auto gather_in_rank = gather->get_input_partial_shape(0).rank(); auto indices_rank = gather->get_input_partial_shape(1).rank(); + auto axis = gather->get_axis(); if (gather_in_rank.is_dynamic() || indices_rank.is_dynamic() || - !gather->is_axis_set()) { + axis == opset3::Gather::AXIS_NOT_SET_VALUE) { NGRAPH_DEBUG << gather << " cannot simplify gather->shapeof"; return false; } - auto axis = gather->get_axis(); auto zero_axis = opset3::Constant::create(element::i64, Shape{}, {0}); NodeVector new_ops; diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/convert_gather_v7_to_gather_v1.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/convert_gather_v7_to_gather_v1.cpp index 67d5c0ebc1c..5e39be3feed 100644 --- a/inference-engine/src/transformations/src/transformations/op_conversions/convert_gather_v7_to_gather_v1.cpp +++ b/inference-engine/src/transformations/src/transformations/op_conversions/convert_gather_v7_to_gather_v1.cpp @@ -22,16 +22,14 @@ ngraph::pass::ConvertGather7ToGather1::ConvertGather7ToGather1() { if (!gather_v7_node) return false; - int64_t batch_dims = 0; - if (gather_v7_node->is_axis_set()) - batch_dims = gather_v7_node->get_batch_dims(); - if (batch_dims != 0) + if (gather_v7_node->get_batch_dims() != 0) return false; + auto data_input = gather_v7_node->input_value(0); auto indices_input = gather_v7_node->input_value(1); auto axis_input = gather_v7_node->input_value(2); - auto gather_v1 = std::make_shared(data_input, indices_input, axis_input); + auto gather_v1 = std::make_shared(data_input, indices_input, axis_input); gather_v1->set_friendly_name(gather_v7_node->get_friendly_name()); ngraph::copy_runtime_info(gather_v7_node, gather_v1); ngraph::replace_node(gather_v7_node, gather_v1); diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_gather_v7_to_gather_v1_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_gather_v7_to_gather_v1_test.cpp index b409ac16738..6d5d309a02f 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_gather_v7_to_gather_v1_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_gather_v7_to_gather_v1_test.cpp @@ -49,3 +49,26 @@ TEST(TransformationTests, ConvertGather7toGather1) { auto res = compare_functions(f, f_ref); ASSERT_TRUE(res.first) << res.second; } + +TEST(TransformationTests, ConvertGather7toGather1_nonzero_batch_dims) { + std::shared_ptr f(nullptr), f_ref(nullptr); + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3}); + auto indices = std::make_shared(ngraph::element::i32, ngraph::Shape{2, 2}); + auto axis = ngraph::opset1::Constant::create(ngraph::element::i32, ngraph::Shape{1}, {1}); + + auto gather_v7 = std::make_shared(data, indices, axis, -1); + + f = std::make_shared(ngraph::NodeVector{gather_v7}, ngraph::ParameterVector{data, indices}); + + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + // if batch_dims != 0 Gather-7 must remain + ASSERT_EQ(count_ops_of_type(f), 0); + ASSERT_EQ(count_ops_of_type(f), 1); +} diff --git a/ngraph/core/include/ngraph/op/gather.hpp b/ngraph/core/include/ngraph/op/gather.hpp index a165e5ddac4..61463363b05 100644 --- a/ngraph/core/include/ngraph/op/gather.hpp +++ b/ngraph/core/include/ngraph/op/gather.hpp @@ -17,6 +17,7 @@ namespace ngraph { public: NGRAPH_RTTI_DECLARATION; + static const int64_t AXIS_NOT_SET_VALUE = std::numeric_limits::max(); Gather() = default; /// \param params The tensor from which slices are gathered /// \param indices Tensor with indexes to gather @@ -26,6 +27,7 @@ namespace ngraph const Output& axis); bool visit_attributes(AttributeVisitor& visitor) override; + int64_t get_axis() const override; std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; @@ -52,6 +54,7 @@ namespace ngraph bool visit_attributes(AttributeVisitor& visitor) override; void validate_and_infer_types() override; + int64_t get_batch_dims() const; std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; diff --git a/ngraph/core/include/ngraph/op/util/gather_base.hpp b/ngraph/core/include/ngraph/op/util/gather_base.hpp index b13c2ad722c..efc40493a7b 100644 --- a/ngraph/core/include/ngraph/op/util/gather_base.hpp +++ b/ngraph/core/include/ngraph/op/util/gather_base.hpp @@ -29,9 +29,7 @@ namespace ngraph const int64_t batch_dims = 0); void validate_and_infer_types() override; - int64_t get_batch_dims() const; - int64_t get_axis() const; - bool is_axis_set() const; + virtual int64_t get_axis() const; bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override; diff --git a/ngraph/core/src/op/gather.cpp b/ngraph/core/src/op/gather.cpp index f68a7a9491a..f2ddc9948b3 100644 --- a/ngraph/core/src/op/gather.cpp +++ b/ngraph/core/src/op/gather.cpp @@ -20,6 +20,13 @@ op::v1::Gather::Gather(const Output& params, constructor_validate_and_infer_types(); } +int64_t ngraph::op::v1::Gather::get_axis() const +{ + if (!get_constant_from_source(input_value(2))) + return AXIS_NOT_SET_VALUE; + return GatherBase::get_axis(); +} + bool ngraph::op::v1::Gather::visit_attributes(AttributeVisitor& visitor) { NGRAPH_OP_SCOPE(v1_Gather_visit_attributes); @@ -58,6 +65,14 @@ void op::v7::Gather::validate_and_infer_types() op::util::GatherBase::validate_and_infer_types(); } +int64_t op::v7::Gather::get_batch_dims() const +{ + if (m_batch_dims < 0 && get_input_partial_shape(1).rank().is_static()) + return m_batch_dims + get_input_partial_shape(1).rank().get_length(); + else + return m_batch_dims; +} + bool ngraph::op::v7::Gather::visit_attributes(AttributeVisitor& visitor) { NGRAPH_OP_SCOPE(v7_Gather_visit_attributes); diff --git a/ngraph/core/src/op/util/gather_base.cpp b/ngraph/core/src/op/util/gather_base.cpp index efc5e476c53..9da96d4849c 100644 --- a/ngraph/core/src/op/util/gather_base.cpp +++ b/ngraph/core/src/op/util/gather_base.cpp @@ -52,26 +52,37 @@ void op::util::GatherBase::validate_and_infer_types() axis_pshape); } - int64_t batch_dims = get_batch_dims(); // will not be converted to positive if axis is not set - if (is_axis_set()) + int64_t batch_dims = m_batch_dims; + if (batch_dims < 0 && indices_rank.is_static()) + { + batch_dims += indices_rank.get_length(); + } + + bool axis_is_set = false; + if (get_constant_from_source(input_value(2))) + axis_is_set = true; + + if (axis_is_set) { int64_t axis = get_axis(); + + // batch_dims, axis both can be positive by default or after normalization if data_rank & + // indices_rank are static. If at least one of them is negative we cannot check their + // consistency. NODE_VALIDATION_CHECK(this, - batch_dims <= axis, + batch_dims <= axis || batch_dims < 0 || axis < 0, "The batch_dims <= axis. But instead got: batch_dims = ", batch_dims, ", axis = ", axis); - if (data_rank.is_static()) - { - NODE_VALIDATION_CHECK(this, - axis >= 0 && axis < data_rank.get_length(), - "The axis must be >= 0 and < data_rank. But instead got axis = ", - axis, - " data_rank = ", - data_rank.get_length()); - } + NODE_VALIDATION_CHECK(this, + (axis >= 0 && axis < data_rank.get_length()) || + data_rank.is_dynamic(), + "The axis must be >= 0 and < data_rank. But instead got axis = ", + axis, + " data_rank = ", + data_rank.get_interval()); } if (indices_rank.is_static() && batch_dims >= 0) @@ -87,62 +98,51 @@ void op::util::GatherBase::validate_and_infer_types() if (data_rank.is_static() && indices_rank.is_static()) { - if (batch_dims >= 0) + auto out_rank = data_rank.get_length() + indices_rank.get_length() - 1 - batch_dims; + PartialShape output_pshape = PartialShape::dynamic(out_rank); + + // implementation of out_shape formula + // data.shape[:batch_dims] + data.shape[batch_dims:axis] + indices.shape[batch_dims:] + + // data.shape[axis + 1:] + int i = 0; + for (; i < batch_dims; i++) { - auto out_rank = data_rank.get_length() + indices_rank.get_length() - 1 - batch_dims; - PartialShape output_pshape = PartialShape::dynamic(out_rank); + NODE_VALIDATION_CHECK(this, + data_pshape[i].compatible(indices_pshape[i]), + "Shapes ", + data_pshape, + " and ", + indices_pshape, + " are not consistent. data and indices must have equal or " + "intersecting sizes until batch_dims"); - // implementation of out_shape formula - // data.shape[:batch_dims] + data.shape[batch_dims:axis] + indices.shape[batch_dims:] + - // data.shape[axis + 1:] - int i = 0; - for (; i < batch_dims; i++) - { - NODE_VALIDATION_CHECK(this, - data_pshape[i].compatible(indices_pshape[i]), - "Shapes ", - data_pshape, - " and ", - indices_pshape, - " are not consistent. data and indices must have equal or " - "intersecting sizes until batch_dims"); - - output_pshape[i] = data_pshape[i] & indices_pshape[i]; - } - - if (is_axis_set()) - { - int64_t axis = get_axis(); - for (; i < axis; i++) - { - output_pshape[i] = data_pshape[i]; - } - for (; i < axis + indices_rank.get_length() - batch_dims; i++) - { - output_pshape[i] = indices_pshape[batch_dims - axis + i]; - } - for (; i < out_rank; i++) - { - output_pshape[i] = data_pshape[batch_dims + 1 - indices_rank.get_length() + i]; - } - } - - set_output_type(0, data_type, output_pshape); + output_pshape[i] = data_pshape[i] & indices_pshape[i]; } - else if (batch_dims < 0) + + if (axis_is_set) { - // batch_dims < 0 could be only if axis is not set - // as soon as axis value will arrive negative batch_dims should be resolved - // batch_dims value will be within [0, data_rank] && [0, indices_rank] - int64_t max_rank = data_rank.get_length() + indices_rank.get_length() - 1; - int64_t min_rank = max_rank - max(data_rank.get_length(), indices_rank.get_length()); - - set_output_type(0, data_type, PartialShape::dynamic(Dimension(min_rank, max_rank))); + int64_t axis = get_axis(); + for (; i < axis; i++) + { + output_pshape[i] = data_pshape[i]; + } + for (; i < axis + indices_rank.get_length() - batch_dims; i++) + { + output_pshape[i] = indices_pshape[batch_dims - axis + i]; + } + for (; i < out_rank; i++) + { + output_pshape[i] = data_pshape[batch_dims + 1 - indices_rank.get_length() + i]; + } } + set_output_type(0, data_type, output_pshape); } else { - set_output_type(0, data_type, PartialShape::dynamic()); + Rank out_rank = data_rank + indices_rank - 1 - batch_dims; + if (batch_dims < 0) + out_rank = out_rank - indices_rank.get_max_length(); + set_output_type(0, data_type, PartialShape::dynamic(out_rank)); } } @@ -164,46 +164,29 @@ int64_t op::util::GatherBase::get_axis() const return axis; } -int64_t op::util::GatherBase::get_batch_dims() const -{ - if (m_batch_dims < 0 && is_axis_set()) - return get_axis() + m_batch_dims; - else - return m_batch_dims; -} - -bool op::util::GatherBase::is_axis_set() const -{ - const auto& axis_constant = get_constant_from_source(input_value(2)); - if (axis_constant) - return true; - else - return false; -} - namespace gather { template bool evaluate(const HostTensorPtr& arg0, const HostTensorPtr& arg1, const HostTensorPtr& out, - size_t axis, - size_t batch_dims) + int64_t axis, + int64_t batch_dims) { using T = typename element_type_traits::value_type; Shape params_shape = arg0->get_shape(); Shape indices_shape = arg1->get_shape(); Shape out_shape(params_shape.size() + indices_shape.size() - 1 - batch_dims); - uint64_t i = 0; + int64_t i = 0; for (; i < axis; i++) { out_shape[i] = params_shape[i]; } - for (uint64_t j = batch_dims; j < indices_shape.size(); i++, j++) + for (int64_t j = batch_dims; j < static_cast(indices_shape.size()); i++, j++) { out_shape[i] = indices_shape[j]; } - for (uint64_t j = axis + 1; j < params_shape.size(); i++, j++) + for (int64_t j = axis + 1; j < static_cast(params_shape.size()); i++, j++) { out_shape[i] = params_shape[j]; } @@ -243,8 +226,8 @@ namespace gather bool evaluate_gather(const HostTensorPtr& arg0, const HostTensorPtr& arg1, const HostTensorPtr& out, - size_t axis, - size_t batch_dims = 0) + int64_t axis, + int64_t batch_dims = 0) { bool rc = true; @@ -358,7 +341,13 @@ bool op::util::GatherBase::evaluate(const HostTensorVector& outputs, axis += input_rank.get_length(); } } - return gather::evaluate_gather(inputs[0], inputs[1], outputs[0], axis, get_batch_dims()); + + int64_t batch_dims = m_batch_dims; + const auto& indices_rank = get_input_partial_shape(1).rank(); + if (batch_dims < 0 && indices_rank.is_static()) + batch_dims += indices_rank.get_length(); + + return gather::evaluate_gather(inputs[0], inputs[1], outputs[0], axis, batch_dims); } bool op::util::GatherBase::evaluate_lower(const HostTensorVector& output_values) const diff --git a/ngraph/test/backend/gather.in.cpp b/ngraph/test/backend/gather.in.cpp index 31a77d7d316..fa2eb79939e 100644 --- a/ngraph/test/backend/gather.in.cpp +++ b/ngraph/test/backend/gather.in.cpp @@ -1181,7 +1181,34 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_v7_data_int32_2d_indices_axis_1_batch_dims_1 test_case.add_input({0, 0, 4, // batch 0 4, 0, 0}); // batch 1 - test_case.add_expected_output(out_shape, {1, 1, 5, // batch 0 + test_case.add_expected_output(out_shape, {1, 1, 5, // batch 0 + 10, 6, 6}); // batch 1 + test_case.run(); + // clang-format on +} + +NGRAPH_TEST(${BACKEND_NAME}, gather_v7_data_int32_2d_indices_axis_1_negative_batch_dims) +{ + Shape data_shape{2, 5}; + Shape indices_shape{2, 3}; + Shape out_shape{2, 3}; + int64_t batch_dims = -1; + int64_t axis = 1; + + auto P = make_shared(element::i32, data_shape); + auto I = make_shared(element::i64, indices_shape); + auto A = op::Constant::create(element::i64, Shape{}, {axis}); + auto G = make_shared(P, I, A, batch_dims); + auto f = make_shared(G, ParameterVector{P, I}); + + // clang-format off + auto test_case = test::TestCase(f); + test_case.add_input({1, 2, 3, 4, 5, // batch 0 + 6, 7, 8, 9, 10}); // batch 1 + + test_case.add_input({0, 0, 4, // batch 0 + 4, 0, 0}); // batch 1 + test_case.add_expected_output(out_shape, {1, 1, 5, // batch 0 10, 6, 6}); // batch 1 test_case.run(); // clang-format on diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index 12dfc479b3a..5273db1149d 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -1614,6 +1614,7 @@ evaluate_mvn_6_across_batch IE_CPU.onnx_mvn_v6 # not yet implemented on CPU/GPU Gather 7 +gather_v7_data_int32_2d_indices_axis_1_negative_batch_dims gather_v7_1d_int32 gather_v7_data_int32_3d_indices_axis_1_batch_dims_1 gather_v7_data_int32_2d_indices_axis_1_batch_dims_1 diff --git a/ngraph/test/type_prop/gather.cpp b/ngraph/test/type_prop/gather.cpp index 35bd4215e7d..a76b24ef57e 100644 --- a/ngraph/test/type_prop/gather.cpp +++ b/ngraph/test/type_prop/gather.cpp @@ -181,24 +181,7 @@ TEST(type_prop, gather_7_negative_axis) ASSERT_EQ(G->get_output_partial_shape(0), out_shape); } -TEST(type_prop, gather_7_batch_dims_1_axis_3) -{ - PartialShape data_shape{Dimension(1, 7), Dimension(1, 3), 200, 400}; - PartialShape indices_shape{Dimension(7, 10), Dimension(2, 10), 3, 8}; - PartialShape out_shape{7, Dimension(1, 3), 200, Dimension(2, 10), 3, 8}; - int64_t axis = 3; - int64_t batch_dims = 1; - - auto D = make_shared(element::f32, data_shape); - auto I = make_shared(element::i64, indices_shape); - auto A = make_shared(element::i64, Shape{1}, vector{axis}); - auto G = make_shared(D, I, A, batch_dims); - - ASSERT_EQ(G->get_element_type(), element::f32); - ASSERT_EQ(G->get_output_partial_shape(0), out_shape); -} - -TEST(type_prop, gather_7_dynamic_batch_dim) +TEST(type_prop, gather_7_dynamic_pshape_batch_dims_1_axis_1) { PartialShape data_shape{Dimension(1, 7), 20, 20}; PartialShape indices_shape{Dimension(7, 10), 3, 8}; @@ -215,7 +198,24 @@ TEST(type_prop, gather_7_dynamic_batch_dim) ASSERT_EQ(G->get_output_partial_shape(0), out_shape); } -TEST(type_prop, gather_7_dynamic_2d_batch_dim) +TEST(type_prop, gather_7_dynamic_pshape_batch_dims_1_axis_3) +{ + PartialShape data_shape{Dimension(1, 7), Dimension(1, 3), 200, 400}; + PartialShape indices_shape{Dimension(7, 10), Dimension(2, 10), 3, 8}; + PartialShape out_shape{7, Dimension(1, 3), 200, Dimension(2, 10), 3, 8}; + int64_t axis = 3; + int64_t batch_dims = 1; + + auto D = make_shared(element::f32, data_shape); + auto I = make_shared(element::i64, indices_shape); + auto A = make_shared(element::i64, Shape{1}, vector{axis}); + auto G = make_shared(D, I, A, batch_dims); + + ASSERT_EQ(G->get_element_type(), element::f32); + ASSERT_EQ(G->get_output_partial_shape(0), out_shape); +} + +TEST(type_prop, gather_7_dynamic_2d_pshape_batch_dim) { PartialShape data_shape{Dimension(1, 7), Dimension(1, 3), 200, 400}; PartialShape indices_shape{Dimension(7, 10), Dimension(2, 10), 3, 8}; @@ -232,7 +232,7 @@ TEST(type_prop, gather_7_dynamic_2d_batch_dim) ASSERT_EQ(G->get_output_partial_shape(0), out_shape); } -TEST(type_prop, gather_7_dynamic_2d_batch_dim_axis_3) +TEST(type_prop, gather_7_dynamic_2d_pshape_batch_dim_axis_3) { PartialShape data_shape{Dimension(1, 7), Dimension(1, 3), 200, 400}; PartialShape indices_shape{Dimension(7, 10), Dimension(2, 10), 3, 8}; @@ -249,11 +249,11 @@ TEST(type_prop, gather_7_dynamic_2d_batch_dim_axis_3) ASSERT_EQ(G->get_output_partial_shape(0), out_shape); } -TEST(type_prop, gather_7_dynamic_data_indices_rank) +TEST(type_prop, gather_7_dynamic_rank) { PartialShape data_shape{Dimension(1, 7), Dimension(1, 3), 200, 400}; - PartialShape indices_shape = PartialShape::dynamic(); - PartialShape out_shape = PartialShape::dynamic(); + PartialShape indices_shape = PartialShape::dynamic(Rank(3, 5)); + PartialShape out_shape = PartialShape::dynamic(Rank(4, 6)); int64_t axis = 3; int64_t batch_dims = 2; @@ -266,6 +266,23 @@ TEST(type_prop, gather_7_dynamic_data_indices_rank) ASSERT_EQ(G->get_output_partial_shape(0), out_shape); } +TEST(type_prop, gather_7_dynamic_rank_negative_batch_dims) +{ + PartialShape data_shape{Dimension(1, 7), Dimension(1, 3), 200, 400}; + PartialShape indices_shape = PartialShape::dynamic(Rank(3, 5)); + PartialShape out_shape = PartialShape::dynamic(Rank(3, 5)); + int64_t axis = 3; + int64_t batch_dims = -2; + + auto D = make_shared(element::f32, data_shape); + auto I = make_shared(element::i64, indices_shape); + auto A = make_shared(element::i64, Shape{1}, vector{axis}); + auto G = make_shared(D, I, A, batch_dims); + + ASSERT_EQ(G->get_element_type(), element::f32); + ASSERT_EQ(G->get_output_partial_shape(0), out_shape); +} + TEST(type_prop, gather_7_axis_not_set) { PartialShape data_shape{1, 1, 200, 400}; @@ -301,25 +318,6 @@ TEST(type_prop, gather_7_axis_not_set_positive_batch_dims) ASSERT_EQ(G->get_output_partial_shape(0), out_shape); } -TEST(type_prop, gather_7_axis_not_set_negative_batch) -{ - PartialShape data_shape{1, 1, 200, 400}; - PartialShape indices_shape{2, 2}; - int64_t batch_dims = -1; - // negative batch_dims together with unknown axis could mean any value - // within the intervals [0, data_rank] && [0, indices_rank] so out_rank will be dynamic with the range - // out_rank = data_rank + indices_rank - 1 - interval(0, max(data_rank, indices_rank)) - PartialShape out_shape = PartialShape::dynamic(Dimension(2, 5)); - - auto D = make_shared(element::f32, data_shape); - auto I = make_shared(element::i64, indices_shape); - auto A = make_shared(element::i32, Shape{1}); - auto G = make_shared(D, I, A, batch_dims); - - ASSERT_EQ(G->get_element_type(), element::f32); - ASSERT_EQ(G->get_output_partial_shape(0), out_shape); -} - // --------------------- Negative tests ------------------------------ TEST(type_prop, gather_7_incorrect_axis_shape) @@ -399,7 +397,7 @@ TEST(type_prop, gather_7_dynamic_batch_dims_inconsistent) TEST(type_prop, gather_7_batch_dims_less_check) { - PartialShape data_shape{1, 20, 20}; + PartialShape data_shape{1, 3, 20}; PartialShape indices_shape{1, 3, 8}; auto D = make_shared(element::f32, data_shape); From 0bac48d5baa2f9aa3d3e2e957fad0c8df90fcb60 Mon Sep 17 00:00:00 2001 From: Vladimir Paramuzov Date: Fri, 14 May 2021 12:12:04 +0300 Subject: [PATCH 61/99] [IE CLDNN] Disable blobs reuse if shapes differ (#5567) --- inference-engine/src/cldnn_engine/cldnn_program.h | 3 ++- inference-engine/src/cldnn_engine/ops/constant.cpp | 5 +++-- inference-engine/src/cldnn_engine/ops/parameter.cpp | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/inference-engine/src/cldnn_engine/cldnn_program.h b/inference-engine/src/cldnn_engine/cldnn_program.h index d8abfd433d4..d741e94580a 100644 --- a/inference-engine/src/cldnn_engine/cldnn_program.h +++ b/inference-engine/src/cldnn_engine/cldnn_program.h @@ -90,7 +90,8 @@ public: std::map outputDims; std::map inputLayouts; - std::map blobMemCache; + using BlobCacheKey = std::pair>; + std::map blobMemCache; int m_max_batch; int m_curBatch; diff --git a/inference-engine/src/cldnn_engine/ops/constant.cpp b/inference-engine/src/cldnn_engine/ops/constant.cpp index 6c5ebc31775..e8630f67a6b 100644 --- a/inference-engine/src/cldnn_engine/ops/constant.cpp +++ b/inference-engine/src/cldnn_engine/ops/constant.cpp @@ -163,7 +163,8 @@ void CreateConstantOp(Program& p, const std::shared_ptrget_data_ptr(); - auto bufIter = p.blobMemCache.find(data); + + auto bufIter = p.blobMemCache.find(std::make_pair(data, constDims)); if (bufIter != p.blobMemCache.end()) { constPrimID = bufIter->second; @@ -198,7 +199,7 @@ void CreateConstantOp(Program& p, const std::shared_ptr(meanBlobPtr->buffer()); - auto bufIter = p.blobMemCache.find(data); + auto bufIter = p.blobMemCache.find(std::make_pair(data, meanDims)); if (bufIter != p.blobMemCache.end()) { meanBlobID = bufIter->second; } else { @@ -166,7 +166,7 @@ void CreateParameterOp(Program& p, const std::shared_ptr Date: Fri, 14 May 2021 13:05:22 +0300 Subject: [PATCH 62/99] [CPU] Reducenode handles negative input (master) (#5494) --- .../src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp | 6 +++--- .../shared_test_classes/src/single_layer/reduce_ops.cpp | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp index 1494705b947..2efea5290f3 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp @@ -1881,13 +1881,13 @@ inline void MKLDNNReduceNode::init_dst_data(uint8_t *out_ptr, size_t dst_size) { case ReduceMax: if (output_prec == Precision::FP32) { auto out_p = reinterpret_cast(out_ptr); - parallel_for(dst_size / dst_data_size, [&](size_t i) { out_p[i] = std::numeric_limits::min(); }); + parallel_for(dst_size / dst_data_size, [&](size_t i) { out_p[i] = std::numeric_limits::lowest(); }); } else if (output_prec == Precision::I32) { auto out_p = reinterpret_cast(out_ptr); parallel_for(dst_size / dst_data_size, [&](size_t i) { out_p[i] = std::numeric_limits::min(); }); } else if (output_prec == Precision::BF16) { auto out_p = reinterpret_cast(out_ptr); - parallel_for(dst_size / dst_data_size, [&](size_t i) { out_p[i] = std::numeric_limits::min(); }); + parallel_for(dst_size / dst_data_size, [&](size_t i) { out_p[i] = std::numeric_limits::lowest(); }); } else if (output_prec == Precision::U8) { auto out_p = reinterpret_cast(out_ptr); parallel_for(dst_size / dst_data_size, [&](size_t i) { out_p[i] = std::numeric_limits::min(); }); @@ -1972,7 +1972,7 @@ inline void MKLDNNReduceNode::reduce_ref(const float *in_ptr, float *out_ptr) { reduce_ref_process(in_ptr, out_ptr, 0, [](float old, float y)->float { return old + expf(y); }); break; case ReduceMax: - reduce_ref_process(in_ptr, out_ptr, std::numeric_limits::min(), + reduce_ref_process(in_ptr, out_ptr, std::numeric_limits::lowest(), [](float x, float y)->float { return x > y ? x : y; }); break; case ReduceMean: diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/reduce_ops.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/reduce_ops.cpp index c410fb0b39d..32dd59edd5a 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/reduce_ops.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/reduce_ops.cpp @@ -78,7 +78,11 @@ InferenceEngine::Blob::Ptr ReduceOpsLayerTest::GenerateInput(const InferenceEngi auto td = info.getTensorDesc(); auto blob = make_blob_with_precision(td); blob->allocate(); - CommonTestUtils::fill_data_random_float(blob, 5, 0, 1000); + if (reductionType == ngraph::helpers::ReductionType::Max) { + CommonTestUtils::fill_data_random_float(blob, 5, -5, 1000); + } else { + CommonTestUtils::fill_data_random_float(blob, 5, 0, 1000); + } return blob; } From 4d1cd0e79d106fdbbbac87d9a72227ae890a591a Mon Sep 17 00:00:00 2001 From: Maksim Derbasov Date: Fri, 14 May 2021 13:08:23 +0300 Subject: [PATCH 63/99] Warnings fix for tests. Spotted by cl compiler (#5616) --- .../src/inference_engine/precision_utils.cpp | 2 +- .../src/subgraph/concat_multi_input.cpp | 2 +- .../src/subgraph/fq_conv_fq_affine.cpp | 2 +- .../src/subgraph/memory_eltwise_reshape_concat.cpp | 2 +- .../src/subgraph/negative_memory_layer_offset.cpp | 4 ++-- .../two_fake_quantize_to_fullyconnected.cpp | 2 +- .../ie_test_utils/common_test_utils/data_utils.hpp | 10 +++++----- .../common_test_utils/xml_net_builder/ir_net.hpp | 2 +- .../include/functional_test_utils/blob_utils.hpp | 14 +++++++------- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/inference-engine/src/inference_engine/precision_utils.cpp b/inference-engine/src/inference_engine/precision_utils.cpp index 0fefd93b576..26ab6455dfa 100644 --- a/inference-engine/src/inference_engine/precision_utils.cpp +++ b/inference-engine/src/inference_engine/precision_utils.cpp @@ -41,7 +41,7 @@ inline float asfloat(uint32_t v) { return f; } -// Function to convert F32 into F16 +// Function to convert F16 into F32 float f16tof32(ie_fp16 x) { // this is storage for output result uint32_t u = static_cast(x); diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/concat_multi_input.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/concat_multi_input.cpp index 4134b941058..b8e33799575 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/concat_multi_input.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/concat_multi_input.cpp @@ -70,7 +70,7 @@ void ConcatMultiInput::GenerateConstOnlyModel() { ngraph::OutputVector concatInputs; const int seed = 0; - std::mt19937 gen(static_cast(seed)); + std::mt19937 gen(seed); auto generateFloatNumbers = [gen](std::size_t vec_len, float min, float max) mutable { std::vector res; diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/fq_conv_fq_affine.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/fq_conv_fq_affine.cpp index 6255b41db01..21ab0789dcd 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/fq_conv_fq_affine.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/fq_conv_fq_affine.cpp @@ -74,7 +74,7 @@ void FqConvFqAffineTest::SetUp() { auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); const int seed = 0; - std::mt19937 gen(static_cast(seed)); + std::mt19937 gen(seed); auto inputFQNode = ngraph::builder::makeFakeQuantize(params[0], ngraph::element::f32, levels[0], std::vector{}, { inputDataMin }, { inputDataMax }, { inputDataMin }, { inputDataMax }); diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_eltwise_reshape_concat.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_eltwise_reshape_concat.cpp index 774230a1c4b..3c4d39558ac 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_eltwise_reshape_concat.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_eltwise_reshape_concat.cpp @@ -33,7 +33,7 @@ void MemoryEltwiseReshapeConcatTest::SetUp() { ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); const int seed = 0; - std::mt19937 gen(static_cast(seed)); + std::mt19937 gen(seed); auto generateFloatNumbers = [gen](std::size_t vec_len, float min, float max) mutable { std::vector res; diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/negative_memory_layer_offset.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/negative_memory_layer_offset.cpp index 51acc473e0e..c11eff780f7 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/negative_memory_layer_offset.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/negative_memory_layer_offset.cpp @@ -30,9 +30,9 @@ namespace SubgraphTestsDefinitions { auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); const int seed = 0; - std::mt19937 gen(static_cast(seed)); + std::mt19937 gen(seed); std::uniform_real_distribution dist(-0.2f, 0.2f); - for (int i = 0; i < hiddenSize; ++i) + for (size_t i = 0; i < hiddenSize; ++i) memory_init.emplace_back(static_cast(dist(gen))); auto input = ngraph::builder::makeParams(ngPrc, { {1, inputSize} }); diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/two_fake_quantize_to_fullyconnected.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/two_fake_quantize_to_fullyconnected.cpp index b4bf7fdcdc2..3b350d426cb 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/two_fake_quantize_to_fullyconnected.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/two_fake_quantize_to_fullyconnected.cpp @@ -68,7 +68,7 @@ void FakeQuantizeSubgraphTest::SetUp() { auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); const int seed = 0; - std::mt19937 gen(static_cast(seed)); + std::mt19937 gen(seed); auto generateFloatNumbers = [gen](std::size_t vec_len, float min, float max) mutable { diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/data_utils.hpp b/inference-engine/tests/ie_test_utils/common_test_utils/data_utils.hpp index 4a41693acd0..e663557617b 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/data_utils.hpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/data_utils.hpp @@ -53,7 +53,7 @@ inline std::vector generate_float_numbers(std::size_t vec_len, float min, */ template inline std::vector fill_vector(std::vector &res, double min, double max, int seed = 0) { - std::mt19937 gen(static_cast(seed)); + std::mt19937 gen(seed); std::uniform_real_distribution dist(min, max); for (std::size_t i = 0; i < res.size(); i++) @@ -231,9 +231,9 @@ void inline fill_data_random(InferenceEngine::Blob::Ptr &blob, const uint32_t ra */ template void inline fill_random_unique_sequence(InferenceEngine::Blob::Ptr &blob, - uint32_t range, - int32_t start_from = 0, - const int32_t k = 1, + uint64_t range, + int64_t start_from = 0, + const int64_t k = 1, const int32_t seed = 1) { using dataType = typename InferenceEngine::PrecisionTrait::value_type; auto *rawBlobDataPtr = blob->buffer().as(); @@ -247,7 +247,7 @@ void inline fill_random_unique_sequence(InferenceEngine::Blob::Ptr &blob, } std::mt19937 generator(seed); - std::uniform_int_distribution dist(k * start_from, k * (start_from + range)); + std::uniform_int_distribution dist(k * start_from, k * (start_from + range)); std::set elems; while (elems.size() != blob->size()) { diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/xml_net_builder/ir_net.hpp b/inference-engine/tests/ie_test_utils/common_test_utils/xml_net_builder/ir_net.hpp index 257cd3f2b52..4d12675988d 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/xml_net_builder/ir_net.hpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/xml_net_builder/ir_net.hpp @@ -88,7 +88,7 @@ public: return std::shared_ptr(new Layer(parent, id, common_attributes)); } - Port &getPortById(int64_t id) const { + Port &getPortById(size_t id) const { if (id >= m_ports.size()) { IE_THROW() << "Out of range: a port with id " << id << " not found"; } diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/blob_utils.hpp b/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/blob_utils.hpp index afb64e4bec6..88a4cf280fb 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/blob_utils.hpp +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/blob_utils.hpp @@ -228,10 +228,10 @@ compareBlobData(const InferenceEngine::Blob::Ptr &res, const InferenceEngine::Bl } for (size_t i = 0; i < ref_size / sizeof(dataType); i++) { - auto resVal = PRC == InferenceEngine::Precision::FP16 ? InferenceEngine::PrecisionUtils::f16tof32(res_ptr[i]) - : res_ptr[i]; - auto refVal = PRC == InferenceEngine::Precision::FP16 ? InferenceEngine::PrecisionUtils::f16tof32(ref_ptr[i]) - : ref_ptr[i]; + auto resVal = PRC == InferenceEngine::Precision::FP16 ? InferenceEngine::PrecisionUtils::f16tof32(static_cast(res_ptr[i])) + : static_cast(res_ptr[i]); + auto refVal = PRC == InferenceEngine::Precision::FP16 ? InferenceEngine::PrecisionUtils::f16tof32(static_cast(ref_ptr[i])) + : static_cast(ref_ptr[i]); float absDiff = std::abs(resVal - refVal); if (absDiff > max_diff) { float relDiff = absDiff / std::max(res_ptr[i], ref_ptr[i]); @@ -286,10 +286,10 @@ compareBlobs(const InferenceEngine::Blob::Ptr &res, const InferenceEngine::Blob: inline void GetComparisonThreshold(InferenceEngine::Precision prc, float &absoluteThreshold, float &relativeThreshold) { switch (prc) { case InferenceEngine::Precision::FP32: - absoluteThreshold = relativeThreshold = 1e-4; + absoluteThreshold = relativeThreshold = 1e-4f; break; case InferenceEngine::Precision::FP16: - absoluteThreshold = relativeThreshold = 1e-2; + absoluteThreshold = relativeThreshold = 1e-2f; break; case InferenceEngine::Precision::I16: case InferenceEngine::Precision::I8: @@ -524,7 +524,7 @@ inline InferenceEngine::Blob::Ptr createAndFillBlobUniqueSequence( InferenceEngine::Blob::Ptr blob = make_blob_with_precision(td); blob->allocate(); auto shape = td.getDims(); - auto range = std::accumulate(begin(shape), end(shape), 1, std::multiplies()) * 2; + auto range = std::accumulate(begin(shape), end(shape), uint64_t(1), std::multiplies()) * 2; switch (td.getPrecision()) { #define CASE(X) case X: CommonTestUtils::fill_random_unique_sequence(blob, range, start_from, resolution, seed); break; CASE(InferenceEngine::Precision::FP32) From b737e6ec964ca302061a2f7cb62f87e33967143e Mon Sep 17 00:00:00 2001 From: Alexandra Sidorova Date: Fri, 14 May 2021 13:22:03 +0300 Subject: [PATCH 64/99] [CPU] Fixed blocked layout conditions for DepthToSpace, SpaceToDepth (#5569) --- .../src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp | 5 +++-- .../src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.cpp | 2 +- .../plugin/cpu/single_layer_tests/depth_to_space.cpp | 4 ++-- .../plugin/cpu/single_layer_tests/space_to_depth.cpp | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp index a91946507d8..2f97bbd2f85 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp @@ -124,7 +124,8 @@ void MKLDNNDepthToSpaceNode::initSupportedPrimitiveDescriptors() { std::vector supportedTypes; if (nDims > 2) { auto canUseBlocked = [=](const size_t block) { - return srcDims[1] % block == 0 && (mode == Mode::BLOCKS_FIRST ? (srcDims[1] / block) % blockStep == 0 : block % blockStep == 0); + return srcDims[1] % block == 0 && (srcDims[1] / block) % blockStep == 0 && + (mode == Mode::DEPTH_FIRST ? block % blockStep == 0 : true); }; supportedTypes.push_back(TensorDescCreatorTypes::nspc); @@ -209,7 +210,7 @@ void MKLDNNDepthToSpaceNode::createPrimitive() { orderShiftForDims = 3; size_t newBlockSize = srcBlockedDims.back() / blockStep; - size_t newBlocksCount = srcBlockedDims[1] * newBlockSize / srcBlockedDims.back(); + size_t newBlocksCount = srcBlockedDims[1] / blockStep; params.src_block_dims[1] = newBlocksCount; params.src_block_dims[2] = srcBlockedDims[1] / newBlocksCount; params.src_block_dims[lastIdx - nSpatialDims] = newBlockSize; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.cpp index 71eb63f62bb..69c3356a2f0 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_space_to_depth_node.cpp @@ -124,7 +124,7 @@ void MKLDNNSpaceToDepthNode::initSupportedPrimitiveDescriptors() { std::vector supportedTypes; if (nDims > 2) { auto canUseBlocked = [=](const size_t block) { - return mode == Mode::DEPTH_FIRST ? block % blockStep == 0 : true; + return srcDims[1] % block == 0 && (mode == Mode::DEPTH_FIRST ? block % blockStep == 0 : true); }; supportedTypes.push_back(TensorDescCreatorTypes::nspc); diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/depth_to_space.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/depth_to_space.cpp index e6bb59179f5..8588d9d2658 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/depth_to_space.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/depth_to_space.cpp @@ -98,7 +98,7 @@ const std::vector depthToSpaceModes = { }; const std::vector> inputShapesBS2_4D = { - {1, 64, 1, 1}, {1, 64, 1, 3}, {1, 128, 3, 3}, {2, 128, 1, 1}, {2, 256, 2, 3} + {1, 64, 1, 1}, {1, 64, 1, 3}, {1, 128, 3, 3}, {2, 128, 1, 1}, {1, 192, 2, 2}, {2, 256, 2, 3}, {1, 512, 2, 1} }; const std::vector> inputShapesBS3_4D = { @@ -145,7 +145,7 @@ const auto depthToSpaceBS3_4DParams = testing::Combine( INSTANTIATE_TEST_CASE_P(smoke_CPUDepthToSpaceBS3_4D, DepthToSpaceLayerCPUTest, depthToSpaceBS3_4DParams, DepthToSpaceLayerCPUTest::getTestCaseName); const std::vector> inputShapesBS2_5D = { - {1, 128, 1, 1, 1}, {1, 128, 2, 1, 2}, {1, 256, 2, 1, 3}, {2, 256, 3, 1, 1}, {2, 512, 1, 2, 1} + {1, 128, 1, 1, 1}, {1, 128, 2, 1, 2}, {1, 256, 2, 1, 3}, {2, 256, 3, 1, 1}, {1, 384, 1, 2, 2}, {2, 512, 1, 2, 1} }; const std::vector> inputShapesBS3_5D = { diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/space_to_depth.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/space_to_depth.cpp index 60c7a431759..a080146064f 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/space_to_depth.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/space_to_depth.cpp @@ -98,7 +98,7 @@ const std::vector spaceToDepthModes = { }; const std::vector> inputShapesBS2_4D = { - {1, 16, 2, 2}, {1, 16, 4, 2}, {1, 32, 6, 8}, {2, 32, 4, 6}, {2, 64, 8, 2}, + {1, 16, 2, 2}, {1, 16, 4, 2}, {1, 32, 6, 8}, {2, 32, 4, 6}, {2, 48, 4, 4}, {2, 64, 8, 2}, }; const std::vector> inputShapesBS3_4D = { @@ -145,7 +145,7 @@ const auto spaceToDepthBS3_4DParams = testing::Combine( INSTANTIATE_TEST_CASE_P(smoke_CPUSpaceToDepthBS3_4D, SpaceToDepthLayerCPUTest, spaceToDepthBS3_4DParams, SpaceToDepthLayerCPUTest::getTestCaseName); const std::vector> inputShapesBS2_5D = { - {1, 16, 2, 2, 2}, {1, 16, 4, 4, 2}, {1, 32, 2, 6, 2}, {2, 32, 4, 2, 2}, {2, 64, 2, 2, 6} + {1, 16, 2, 2, 2}, {1, 16, 4, 4, 2}, {1, 32, 2, 6, 2}, {2, 32, 4, 2, 2}, {1, 48, 6, 2, 2}, {2, 64, 2, 2, 6} }; const std::vector> inputShapesBS3_5D = { From c9672ee9ecf59effb500c73b2a8c93a778ca1225 Mon Sep 17 00:00:00 2001 From: azhogov Date: Fri, 14 May 2021 13:41:35 +0300 Subject: [PATCH 65/99] Azure CI: Exclude IE_CPU.exp_* nGraph UT on Mac --- .ci/azure/mac.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/azure/mac.yml b/.ci/azure/mac.yml index 3ba29d392c0..66ee0885a24 100644 --- a/.ci/azure/mac.yml +++ b/.ci/azure/mac.yml @@ -105,7 +105,7 @@ jobs: workingDirectory: $(BUILD_DIR) displayName: 'Install' - - script: $(BIN_DIR)/unit-test --gtest_print_time=1 --gtest_filter=-backend_api.config_unsupported:*IE_GPU*:IE_CPU.onnx_model_sigmoid:IE_CPU/GRUSequenceOp.onnx_model_gru* --gtest_output=xml:TEST-NGraphUT.xml + - script: $(BIN_DIR)/unit-test --gtest_print_time=1 --gtest_filter=-backend_api.config_unsupported:*IE_GPU*:IE_CPU.onnx_model_sigmoid:IE_CPU/GRUSequenceOp.onnx_model_gru*:IE_CPU.exp_* --gtest_output=xml:TEST-NGraphUT.xml displayName: 'nGraph UT' continueOnError: false From d2c9bddff13b332acb23947d68f1536b874ef780 Mon Sep 17 00:00:00 2001 From: Vladislav Volkov Date: Fri, 14 May 2021 13:48:02 +0300 Subject: [PATCH 66/99] Convert operation optimization for FP16 -> INT8 and FP32 -> INT8 (#5275) Improvements for ConvertPrecision transformation pass --- docs/template_plugin/src/template_plugin.cpp | 2 +- .../src/cldnn_engine/cldnn_engine.cpp | 8 +- .../src/mkldnn_plugin/mkldnn_plugin.cpp | 46 +-- .../convert_to_cpu_specific_opset.hpp | 2 +- .../transformations/convert_precision.hpp | 15 +- .../common/include/vpu/ngraph/utilities.hpp | 3 +- .../src/frontend/frontend.cpp | 13 +- .../convert_ngraph_to_cnn_network_tests.cpp | 9 +- .../transformations/convert_precision.cpp | 161 ++++++--- .../ngraph/runtime/reference/convert.hpp | 5 +- .../src/runtime/reference/convert.cpp | 125 +++++-- .../src/runtime/reference/jit_generator.cpp | 20 ++ ngraph/core/src/pass/convert_fp32_to_fp16.cpp | 3 +- ngraph/core/src/pass/convert_precision.cpp | 323 +++++++++++------- ngraph/test/backend/convert.in.cpp | 19 ++ 15 files changed, 519 insertions(+), 235 deletions(-) diff --git a/docs/template_plugin/src/template_plugin.cpp b/docs/template_plugin/src/template_plugin.cpp index 061d2c40d4d..6da16cce891 100644 --- a/docs/template_plugin/src/template_plugin.cpp +++ b/docs/template_plugin/src/template_plugin.cpp @@ -67,7 +67,7 @@ std::shared_ptr TransformNetwork(const std::shared_ptr(); // Template plugin handles only FP32 networks - passManager.register_pass(ngraph::element::f16, ngraph::element::f32); + passManager.register_pass(precisions_array {{ngraph::element::f16, ngraph::element::f32 }}); // Example: register plugin specific transformation passManager.register_pass(); passManager.register_pass(); diff --git a/inference-engine/src/cldnn_engine/cldnn_engine.cpp b/inference-engine/src/cldnn_engine/cldnn_engine.cpp index b963d96a16f..0bea81eface 100644 --- a/inference-engine/src/cldnn_engine/cldnn_engine.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_engine.cpp @@ -175,7 +175,7 @@ InferenceEngine::CNNNetwork clDNNEngine::CloneAndTransformNetwork(const Inferenc manager.register_pass(); manager.register_pass(); - std::vector> convert_precision_list { + static const precisions_array convert_precision_list { {ngraph::element::i64, ngraph::element::i32}, {ngraph::element::u64, ngraph::element::i32}, {ngraph::element::u16, ngraph::element::i32}, @@ -185,9 +185,7 @@ InferenceEngine::CNNNetwork clDNNEngine::CloneAndTransformNetwork(const Inferenc {ngraph::element::u4, ngraph::element::u8}, }; - for (auto& precision : convert_precision_list) { - manager.register_pass(precision.first, precision.second); - } + manager.register_pass(convert_precision_list); auto pass_config = manager.get_pass_config(); @@ -366,7 +364,7 @@ InferenceEngine::CNNNetwork clDNNEngine::CloneAndTransformNetwork(const Inferenc // Conversion to FP32 might be needed for quantized models that face any fp16 related issues (e.g. overflow) for non-quantized layers // With this key users can work-around such issues if (!config.enable_fp16_for_quantized_models) { - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + manager.register_pass(precisions_array {{ ngraph::element::f16, ngraph::element::f32 }}); } auto lptPrerequisites = manager.register_pass(); const std::vector supportedTypes = { ngraph::element::i8, ngraph::element::u8 }; diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index a597a1233e4..162c3a530ba 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,7 @@ #include #include #include +#include #include @@ -122,6 +124,28 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { std::vector{ ngraph::element::i8, ngraph::element::u8, ngraph::element::i4, ngraph::element::u4 }); } + auto get_convert_precisions = []() { + precisions_array array = { + {ngraph::element::i64, ngraph::element::i32}, + {ngraph::element::u64, ngraph::element::i32}, + {ngraph::element::i16, ngraph::element::i32}, + {ngraph::element::u16, ngraph::element::i32}, + {ngraph::element::u32, ngraph::element::i32}, + {ngraph::element::f64, ngraph::element::f32}, + {ngraph::element::f16, ngraph::element::f32}, + {ngraph::element::boolean, ngraph::element::u8}, + {ngraph::element::i4, ngraph::element::i8}, + {ngraph::element::u4, ngraph::element::u8} + }; + + if (!with_cpu_x86_avx512_core()) + array.push_back({ngraph::element::bf16, ngraph::element::f32}); + + return array; + }; + + static const auto precisions = get_convert_precisions(); + // WA: ConvertPriorBox must be executed before the 1st ConstantFolding pass manager.register_pass(); manager.register_pass(); @@ -140,27 +164,7 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { manager.register_pass(); manager.register_pass(); manager.register_pass(); - - std::vector> convert_precision_list{ - {ngraph::element::i64, ngraph::element::i32}, - {ngraph::element::u64, ngraph::element::i32}, - {ngraph::element::i16, ngraph::element::i32}, - {ngraph::element::u16, ngraph::element::i32}, - {ngraph::element::u32, ngraph::element::i32}, - {ngraph::element::f64, ngraph::element::f32}, - {ngraph::element::f16, ngraph::element::f32}, - {ngraph::element::boolean, ngraph::element::u8}, - {ngraph::element::i4, ngraph::element::i8}, - {ngraph::element::u4, ngraph::element::u8}, - }; - - // In case BF16 is not supported by the target CPU we explicitly convert it to FP32 - if (!with_cpu_x86_avx512_core()) - convert_precision_list.push_back({ngraph::element::bf16, ngraph::element::f32}); - - for (auto &precision : convert_precision_list) { - manager.register_pass(precision.first, precision.second); - } + manager.register_pass(precisions); auto pass_config = manager.get_pass_config(); diff --git a/inference-engine/src/mkldnn_plugin/ngraph_transformations/convert_to_cpu_specific_opset.hpp b/inference-engine/src/mkldnn_plugin/ngraph_transformations/convert_to_cpu_specific_opset.hpp index 8496558e614..9f73446f95a 100644 --- a/inference-engine/src/mkldnn_plugin/ngraph_transformations/convert_to_cpu_specific_opset.hpp +++ b/inference-engine/src/mkldnn_plugin/ngraph_transformations/convert_to_cpu_specific_opset.hpp @@ -42,7 +42,7 @@ inline void ConvertToCPUSpecificOpset(std::shared_ptr &nGraphF manager.register_pass(); } manager.register_pass(); - manager.register_pass(ngraph::element::i64, ngraph::element::i32); + manager.register_pass(precisions_array {{ ngraph::element::i64, ngraph::element::i32 }}); manager.run_passes(nGraphFunc); } diff --git a/inference-engine/src/transformations/include/transformations/convert_precision.hpp b/inference-engine/src/transformations/include/transformations/convert_precision.hpp index 41603f508d6..56ea4dba7b9 100644 --- a/inference-engine/src/transformations/include/transformations/convert_precision.hpp +++ b/inference-engine/src/transformations/include/transformations/convert_precision.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -69,18 +70,24 @@ class NGRAPH_API ConvertPrecision; * LessEqual */ -using type_to_fuse_map = std::map&, ngraph::element::Type, size_t idx)>>; +using type_to_fuse_map = std::unordered_map&, ngraph::element::Type, size_t idx)>>; +using precisions_array = std::vector>; + class ngraph::pass::ConvertPrecision : public ngraph::pass::FunctionPass { public: NGRAPH_RTTI_DECLARATION; ConvertPrecision(ngraph::element::Type_t from, ngraph::element::Type_t to, type_to_fuse_map additional_type_to_fuse_map = {}) : FunctionPass(), - m_from(from), - m_to(to), + m_precisions(precisions_array {{ from, to }}), + m_additional_type_to_fuse_map(additional_type_to_fuse_map) {} + + ConvertPrecision(const precisions_array& precisions, const type_to_fuse_map & additional_type_to_fuse_map = {}) + : FunctionPass(), + m_precisions(precisions), m_additional_type_to_fuse_map(additional_type_to_fuse_map) {} bool run_on_function(std::shared_ptr f) override; private: - element::Type m_from, m_to; + precisions_array m_precisions; type_to_fuse_map m_additional_type_to_fuse_map; }; diff --git a/inference-engine/src/vpu/common/include/vpu/ngraph/utilities.hpp b/inference-engine/src/vpu/common/include/vpu/ngraph/utilities.hpp index bf37a6ea981..f5290534cbe 100644 --- a/inference-engine/src/vpu/common/include/vpu/ngraph/utilities.hpp +++ b/inference-engine/src/vpu/common/include/vpu/ngraph/utilities.hpp @@ -15,10 +15,11 @@ #include "vpu/ngraph/operations/out_shape_of_reshape.hpp" #include #include +#include namespace vpu { -using typeToFuseMap = std::map&, ngraph::element::Type, size_t idx)>>; +using typeToFuseMap = std::unordered_map&, ngraph::element::Type, size_t idx)>>; bool fuseTypeToStaticShapeNonMaxSuppression(const std::shared_ptr& node, ngraph::element::Type to, size_t idx); bool fuseTypeToStaticShapeNonZero(const std::shared_ptr& node, ngraph::element::Type to, size_t idx); diff --git a/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp b/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp index 91e9be21adb..92e1448e127 100644 --- a/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp @@ -192,14 +192,17 @@ ie::CNNNetwork FrontEnd::convertNetwork(ie::CNNNetwork& network) { manager.register_pass(); manager.register_pass(); // ConvertPrecision must be executed before ConvertOpSet1ToLegacy due to this pass works with operations from opsets only - manager.register_pass(ngraph::element::i64, ngraph::element::i32, myriadTypeToFuseMap); - manager.register_pass(ngraph::element::u64, ngraph::element::i32, myriadTypeToFuseMap); - manager.register_pass(ngraph::element::u32, ngraph::element::i32, myriadTypeToFuseMap); - manager.register_pass(ngraph::element::boolean, ngraph::element::i32, myriadTypeToFuseMap); + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::u64, ngraph::element::i32 }, + { ngraph::element::u32, ngraph::element::i32 }, + { ngraph::element::boolean, ngraph::element::i32 } + }; + manager.register_pass(precisions, myriadTypeToFuseMap); manager.register_pass(); // ConvertOpSet1ToLegacy can produce constants with I64 precision - manager.register_pass(ngraph::element::i64, ngraph::element::i32, myriadTypeToFuseMap); + manager.register_pass(precisions_array {{ ngraph::element::i64, ngraph::element::i32 }}, myriadTypeToFuseMap); manager.register_pass(); auto pass_config = manager.get_pass_config(); diff --git a/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp b/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp index 5a298ed4f41..18a4f6ace4f 100644 --- a/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp @@ -174,7 +174,7 @@ TEST(ConvertFunctionToCNNNetworkTests, ConvertTopKWithOneInput) { manager.register_pass(); manager.register_pass(); - std::vector> convert_precision_list { + static const precisions_array convert_precision_list { {ngraph::element::i64, ngraph::element::i32}, {ngraph::element::u64, ngraph::element::i32}, {ngraph::element::u16, ngraph::element::i32}, @@ -183,12 +183,9 @@ TEST(ConvertFunctionToCNNNetworkTests, ConvertTopKWithOneInput) { {ngraph::element::boolean, ngraph::element::u8}, }; - for (auto & precision : convert_precision_list) { - manager.register_pass(precision.first, precision.second); - } - + manager.register_pass(convert_precision_list); manager.register_pass(); - manager.register_pass(ngraph::element::i64, ngraph::element::i32); + manager.register_pass(precisions_array {{ ngraph::element::i64, ngraph::element::i32 }}); manager.run_passes(f); diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_precision.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_precision.cpp index ea9fda3016b..1bbe676543c 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_precision.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_precision.cpp @@ -54,8 +54,13 @@ TEST(TransformationTests, ConvertPrecision_NMS3) { f = std::make_shared(NodeVector{nms}, ParameterVector{boxes, scores}); pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -77,8 +82,13 @@ TEST(TransformationTests, ConvertPrecision_NMS4) { f = std::make_shared(NodeVector{nms}, ParameterVector{boxes, scores}); pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -95,8 +105,13 @@ TEST(TransformationTests, ConvertPrecision_ShapeOf) { f = std::make_shared(NodeVector{shape_of}, ParameterVector{input}); pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -113,8 +128,13 @@ TEST(TransformationTests, ConvertPrecision_Convert) { f = std::make_shared(NodeVector{convert}, ParameterVector{input}); pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -132,7 +152,7 @@ TEST(TransformationTests, ConvertPrecision_ConvertElimination) { f = std::make_shared(NodeVector{convert}, ParameterVector{input}); pass::Manager manager; - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + manager.register_pass(precisions_array {{ ngraph::element::f16, ngraph::element::f32 }}); manager.run_passes(f); ASSERT_FALSE(has_type(f)); } @@ -158,8 +178,13 @@ TEST(TransformationTests, ConvertPrecision_TopK) { f = std::make_shared(OutputVector{topk->output(0), topk->output(1)}, ParameterVector{input}); pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -176,8 +201,13 @@ TEST(TransformationTests, ConvertPrecision_NonZero) { f = std::make_shared(OutputVector{non_zero}, ParameterVector{input}); pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -195,8 +225,13 @@ TEST(TransformationTests, ConvertPrecision_Bucketize) { f = std::make_shared(OutputVector{b}, ParameterVector{input}); pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -223,8 +258,13 @@ TEST(TransformationTests, ConvertPrecision_Roundings) { f = std::make_shared(OutputVector{ss}, ParameterVector{input}); pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); auto casted_end = std::dynamic_pointer_cast(ss->input_value(2).get_node_shared_ptr()); @@ -279,8 +319,13 @@ TEST(TransformationTests, ConvertPrecision_TIBody) { ngraph::ParameterVector{X, Y}); ngraph::pass::Manager manager; - manager.register_pass(ngraph::element::i64, ngraph::element::i32); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::i64, ngraph::element::i32 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); ASSERT_FALSE(has_type(f)); @@ -300,8 +345,13 @@ TEST(TransformationTests, ConvertPrecision_Equal) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::boolean, ngraph::element::u8 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -320,8 +370,13 @@ TEST(TransformationTests, ConvertPrecision_NotEqual) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::boolean, ngraph::element::u8 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -340,8 +395,13 @@ TEST(TransformationTests, ConvertPrecision_Greater) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::boolean, ngraph::element::u8 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -360,8 +420,13 @@ TEST(TransformationTests, ConvertPrecision_GreaterEqual) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::boolean, ngraph::element::u8 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -380,8 +445,13 @@ TEST(TransformationTests, ConvertPrecision_Less) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::boolean, ngraph::element::u8 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -400,8 +470,13 @@ TEST(TransformationTests, ConvertPrecision_LessEqual) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + + static const precisions_array precisions = { + { ngraph::element::boolean, ngraph::element::u8 }, + { ngraph::element::f16, ngraph::element::f32 } + }; + + manager.register_pass(precisions); manager.run_passes(f); } @@ -420,7 +495,7 @@ TEST(TransformationTests, ConvertPrecision_LogicalAnd) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); + manager.register_pass(precisions_array {{ ngraph::element::boolean, ngraph::element::u8 }}); manager.run_passes(f); } @@ -438,7 +513,7 @@ TEST(TransformationTests, ConvertPrecision_LogicalOr) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); + manager.register_pass(precisions_array {{ ngraph::element::boolean, ngraph::element::u8 }}); manager.run_passes(f); } @@ -456,7 +531,7 @@ TEST(TransformationTests, ConvertPrecision_LogicalXor) { f = std::make_shared(OutputVector{node}, ParameterVector{input1, input2}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); + manager.register_pass(precisions_array {{ ngraph::element::boolean, ngraph::element::u8 }}); manager.run_passes(f); } @@ -473,7 +548,7 @@ TEST(TransformationTests, ConvertPrecision_LogicalNot) { f = std::make_shared(OutputVector{node}, ParameterVector{input1}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); + manager.register_pass(precisions_array {{ ngraph::element::boolean, ngraph::element::u8 }}); manager.run_passes(f); } @@ -491,7 +566,7 @@ TEST(TransformationTests, ConvertPrecision_Select) { f = std::make_shared(OutputVector{select}, ParameterVector{input1}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::u8); + manager.register_pass(precisions_array {{ ngraph::element::boolean, ngraph::element::u8 }}); manager.run_passes(f); } @@ -509,8 +584,8 @@ TEST(TransformationTests, ConvertPrecision_TypeRelaxedWithSelect) { f = std::make_shared(OutputVector{select}, ParameterVector{input1}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::i32); - manager.register_pass(ngraph::element::i32, ngraph::element::i64); + manager.register_pass(precisions_array {{ ngraph::element::boolean, ngraph::element::i32 }}); + manager.register_pass(precisions_array {{ ngraph::element::i32, ngraph::element::i64 }}); manager.run_passes(f); } @@ -529,8 +604,8 @@ TEST(TransformationTests, ConvertPrecision_TypeRelaxed) { f = std::make_shared(OutputVector{type_relaxed}, ParameterVector{input1}); pass::Manager manager; - manager.register_pass(ngraph::element::boolean, ngraph::element::i32); - manager.register_pass(ngraph::element::i32, ngraph::element::i64); + manager.register_pass(precisions_array {{ ngraph::element::boolean, ngraph::element::i32 }}); + manager.register_pass(precisions_array {{ ngraph::element::i32, ngraph::element::i64 }}); manager.run_passes(f); ASSERT_FALSE(has_type(f)); @@ -555,7 +630,7 @@ TEST(TransformationTests, ConvertPrecision_Variables) { f = std::make_shared(NodeVector{mul}, ParameterVector{inp}); pass::Manager manager; - manager.register_pass(ngraph::element::f16, ngraph::element::f32); + manager.register_pass(precisions_array {{ ngraph::element::f16, ngraph::element::f32 }}); manager.run_passes(f); } @@ -573,7 +648,7 @@ void constant_convert_test(element::Type type_from, element::Type type_to, const f = std::make_shared(NodeVector{c}, ParameterVector{}); pass::Manager manager; - manager.register_pass(type_from, type_to); + manager.register_pass(precisions_array {{ type_from, type_to }}); manager.run_passes(f); } auto ops = f->get_ordered_ops(); @@ -603,7 +678,7 @@ void constant_convert_test(element::Type_t type_from, element::Type_t type_to, F f = std::make_shared(NodeVector{c}, ParameterVector{}); pass::Manager manager; - manager.register_pass(type_from, type_to); + manager.register_pass(precisions_array {{ type_from, type_to }}); manager.run_passes(f); } auto ops = f->get_ordered_ops(); diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/convert.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/convert.hpp index 8591f88c794..ecaf92ffd61 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/convert.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/convert.hpp @@ -28,6 +28,10 @@ namespace ngraph void convert(const uint8_t* arg, float16* out, size_t count); template <> void convert(const float16* arg, float* out, size_t count); + template <> + void convert(const float* arg, int8_t* out, size_t count); + template <> + void convert(const float16* arg, int8_t* out, size_t count); // overload to handle ngraph::boolean (it is stored as char) template @@ -39,7 +43,6 @@ namespace ngraph out[i] = static_cast(static_cast(arg[i])); } } - } // namespace reference } // namespace runtime diff --git a/ngraph/core/reference/src/runtime/reference/convert.cpp b/ngraph/core/reference/src/runtime/reference/convert.cpp index 809c9ca3dc5..78625f38c9e 100644 --- a/ngraph/core/reference/src/runtime/reference/convert.cpp +++ b/ngraph/core/reference/src/runtime/reference/convert.cpp @@ -16,6 +16,11 @@ namespace ngraph template void jit_convert_vec(jit::Generator&, const Xbyak::RegExp&, const Xbyak::RegExp&); + template + void jit_convert_vec_prepare(jit::Generator&) + { + } + template <> void jit_convert_vec(jit::Generator& gen, const Xbyak::RegExp& src, @@ -47,6 +52,61 @@ namespace ngraph gen.vmovups(gen.yword[dst], f32vec); } + template <> + void jit_convert_vec_prepare(jit::Generator& gen) + { + auto order = gen.ymm1; + auto addr = gen.r15; + + static const int8_t offsets[32] = {0, 4, 8, 12, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 4, + 8, 12, -1, -1, -1, -1, -1, -1, -1, -1}; + + gen.mov(addr, (size_t)offsets); // get offsets[] address + gen.vmovdqu(order, gen.yword[addr]); // save offsets[] to ymm register + } + + template <> + void jit_convert_vec(jit::Generator& gen, + const Xbyak::RegExp& src, + const Xbyak::RegExp& dst) + { + auto order = gen.ymm1; + auto p32vec = gen.ymm2; + auto p32vec_lo = gen.xmm2; + auto p32vec_hi = gen.xmm3; + + gen.vcvtps2dq(p32vec, gen.yword[src]); // convert 8 floats to 8 ints + gen.vpshufb(p32vec, p32vec, order); // Shuffle the bytes according to the order + gen.vextracti128(p32vec_hi, p32vec, 1); // extract upper part of p32vec + gen.vpor(p32vec_lo, p32vec_lo, p32vec_hi); // p32vec_lo = p32vec_lo | p32vec_hi + gen.movq(gen.qword[dst], p32vec_lo); // save the result + } + + template <> + void jit_convert_vec_prepare(jit::Generator& gen) + { + jit_convert_vec_prepare(gen); + } + + template <> + void jit_convert_vec(jit::Generator& gen, + const Xbyak::RegExp& src, + const Xbyak::RegExp& dst) + { + auto order = gen.ymm1; + auto p32vec = gen.ymm2; + auto p32vec_lo = gen.xmm2; + auto p32vec_hi = gen.xmm3; + + gen.vcvtph2ps(p32vec, gen.xword[src]); // convert 8 fp16's to 8 floats + gen.vcvtps2dq(p32vec, p32vec); // convert 8 floats to 8 ints + gen.vpshufb(p32vec, p32vec, order); // Shuffle the bytes according to the order + gen.vextracti128(p32vec_hi, p32vec, 1); // extract upper part of p32vec + gen.vpor(p32vec_lo, p32vec_lo, p32vec_hi); // p32vec_lo = p32vec_lo | p32vec_hi + gen.movq(gen.qword[dst], p32vec_lo); // save the result + } + class jit_convert_array : public jit::Generator { typedef struct context @@ -61,6 +121,7 @@ namespace ngraph void (*convert_vec)(jit::Generator&, const Xbyak::RegExp&, const Xbyak::RegExp&); + void (*prepare)(jit::Generator&); } context_t; jit_convert_array(const context_t& ctx) @@ -77,6 +138,8 @@ namespace ngraph preamble(); + ctx.prepare(*this); + mov(reg_src, ptr[param + offsetof(args_t, src)]); mov(reg_dst, ptr[param + offsetof(args_t, out)]); mov(reg_sz, ptr[param + offsetof(args_t, count)]); @@ -137,7 +200,8 @@ namespace ngraph static const jit_convert_array::context_t context{ {sizeof(src_t), &jit::Generator::copy}, {sizeof(dst_t), &jit::Generator::copy}, - jit_convert_vec}; + jit_convert_vec, + jit_convert_vec_prepare}; static jit_convert_array generator(context); @@ -146,44 +210,49 @@ namespace ngraph return nullptr; } }; + + template + void convert_impl(const TI* arg, TO* out, size_t count) + { + auto converter = jit_convert_array::get(); + + if (converter) + { + jit_convert_array::args_t args = {arg, out, count}; + converter(&args); + } + else + { + for (size_t i = 0; i < count; ++i) + { + out[i] = static_cast(arg[i]); + } + } + } } // namespace template <> void convert(const uint8_t* arg, float16* out, size_t count) { - auto converter = jit_convert_array::get(); - - if (converter) - { - jit_convert_array::args_t args = {arg, out, count}; - converter(&args); - } - else - { - for (size_t i = 0; i < count; ++i) - { - out[i] = static_cast(arg[i]); - } - } + convert_impl(arg, out, count); } template <> void convert(const float16* arg, float* out, size_t count) { - auto converter = jit_convert_array::get(); + convert_impl(arg, out, count); + } - if (converter) - { - jit_convert_array::args_t args = {arg, out, count}; - converter(&args); - } - else - { - for (size_t i = 0; i < count; ++i) - { - out[i] = static_cast(arg[i]); - } - } + template <> + void convert(const float* arg, int8_t* out, size_t count) + { + convert_impl(arg, out, count); + } + + template <> + void convert(const float16* arg, int8_t* out, size_t count) + { + convert_impl(arg, out, count); } } // namespace reference } // namespace runtime diff --git a/ngraph/core/reference/src/runtime/reference/jit_generator.cpp b/ngraph/core/reference/src/runtime/reference/jit_generator.cpp index 783fa6a715d..0f4d5a26f53 100644 --- a/ngraph/core/reference/src/runtime/reference/jit_generator.cpp +++ b/ngraph/core/reference/src/runtime/reference/jit_generator.cpp @@ -158,6 +158,26 @@ namespace ngraph pop(rsi); } + template <> + void Generator::copy(const Xbyak::Reg64& dst, + const Xbyak::Reg64& src, + const Xbyak::Reg64& size) + { + push(rsi); + push(r15); + + xor_(rsi, rsi); + + foreach (rsi, 1, size, [&, this](const Xbyak::Reg64& idx) { + mov(r15b, byte[src + idx * sizeof(int8_t)]); + mov(byte[dst + idx * sizeof(int8_t)], r15b); + }) + ; + + pop(r15); + pop(rsi); + } + template <> void Generator::copy(const Xbyak::Reg64& dst, const Xbyak::Reg64& src, diff --git a/ngraph/core/src/pass/convert_fp32_to_fp16.cpp b/ngraph/core/src/pass/convert_fp32_to_fp16.cpp index 077b36593da..c841852a2f3 100644 --- a/ngraph/core/src/pass/convert_fp32_to_fp16.cpp +++ b/ngraph/core/src/pass/convert_fp32_to_fp16.cpp @@ -15,7 +15,8 @@ NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertFP32ToFP16, "ConvertFP32ToFP16", 0); bool ngraph::pass::ConvertFP32ToFP16::run_on_function(std::shared_ptr f) { ngraph::pass::Manager m(get_pass_config()); - m.register_pass(ngraph::element::f32, ngraph::element::f16); + m.register_pass( + precisions_array{{ngraph::element::f32, ngraph::element::f16}}); m.run_passes(f); return false; } diff --git a/ngraph/core/src/pass/convert_precision.cpp b/ngraph/core/src/pass/convert_precision.cpp index 2d5a0ab5eae..8fdef4c9356 100644 --- a/ngraph/core/src/pass/convert_precision.cpp +++ b/ngraph/core/src/pass/convert_precision.cpp @@ -125,6 +125,194 @@ bool fuse_type_to_reduce_logical(const std::shared_ptr& node, return false; } +namespace +{ + void validate_nodes_and_infer_types(const std::vector>& ops) + { + for (auto& node : ops) + { + node->revalidate_and_infer_types(); + } + } + + bool convert_precision(pass::PassBase& pass, + const std::shared_ptr& f, + const type_to_fuse_map& type_to_fuse, + const type_to_fuse_map& type_to_extend, + element::Type from, + element::Type to) + { + // As Constant operations can be shared between multiple nGraph Functions so before + // changing precision we need to understand which Constant consumers belongs + // to the current nGraph Function + std::unordered_map>> const_to_internal_output; + + auto register_constants = + [&const_to_internal_output](const std::vector>& ops) { + for (auto& node : ops) + { + for (auto& input : node->inputs()) + { + if (auto const_node = std::dynamic_pointer_cast( + input.get_source_output().get_node_shared_ptr())) + { + const_to_internal_output[const_node.get()].emplace_back(input); + } + } + } + }; + + auto convert_node_output_precision = [&](const std::shared_ptr& node) { + for (auto output : node->outputs()) + { + if (output.get_element_type() == from) + { + // Handle case with Constants as they can have consumers from other nGraph + // Function object + auto it = const_to_internal_output.find(node.get()); + if (it != const_to_internal_output.end()) + { + return fuse_type_to_constant(node, to, it->second); + } + + // Check that node type exists in map and we can fuse type into node + auto t2f_it = type_to_fuse.find(node->get_type_info()); + if (t2f_it != type_to_fuse.end() && + t2f_it->second(node, to, output.get_index())) + { + // We need to break if original node was replaced + return true; + } + } + } + return false; + }; + + auto convert_node_input_precision = [&](const std::shared_ptr& node) { + for (auto input : node->inputs()) + { + if (input.get_element_type() == from) + { + // For some operations we need to extend their input types to support new type + auto it = type_to_extend.find(node->get_type_info()); + if (it != type_to_extend.end() && it->second(node, to, input.get_index())) + { + return true; + } + } + } + return false; + }; + + std::function&, bool)> convert_function_precision = + [&](const std::shared_ptr& f, bool is_subgraph) { + bool is_changed = false; + + auto ops = f->get_ordered_ops(); + + // Iterate over all nodes in topological order and then iterate over node outputs. + // If output type mismatch given type we try to fuse type into this operation + // otherwise we insert Convert operation. + for (auto& node : ops) + { + pass.transformation_callback(node); + // Recursively apply transformation for sub-graph based operations + if (auto sub_graph_node = std::dynamic_pointer_cast(node)) + { + if (auto sub_graph = sub_graph_node->get_function()) + { + is_changed |= convert_function_precision(sub_graph, true); + } + } + is_changed |= convert_node_input_precision(node); + } + + if (is_changed) + ops = f->get_ordered_ops(); + + // Register internal constants only after fixing input type that could lead to nodes + // replacement + register_constants(ops); + + bool is_output_precision_changed = false; + + for (auto& node : ops) + { + is_output_precision_changed |= convert_node_output_precision(node); + } + + if (is_output_precision_changed) + { + ops = f->get_ordered_ops(); + is_changed |= is_output_precision_changed; + } + + if (!is_subgraph) + { + if (is_changed) + validate_nodes_and_infer_types(ops); + + // TODO: we need to split NopElimination pass to separate MatcherPasses and call + // Convert elimination here + for (auto& node : ops) + { + if (auto convert = std::dynamic_pointer_cast(node)) + { + // WA for topK, dont remove fake convert + if (convert->input(0).get_element_type() == + convert->get_convert_element_type() && + convert->input_value(0).get_node_shared_ptr()->get_output_size() == + 1) + { + replace_output_update_name(convert->output(0), + convert->input_value(0)); + } + } + } + } + + return is_changed; + }; + + return convert_function_precision(f, false); + } + + struct EnumClassHash + { + template + std::size_t operator()(T t) const + { + return static_cast(t); + } + }; + + using precisions_set_t = std::unordered_set; + + precisions_set_t find_all_used_precisions(const std::shared_ptr& fn) + { + precisions_set_t used_precisions; + + ngraph::traverse_nodes(fn, [&](std::shared_ptr node) { + for (auto output : node->outputs()) + { + used_precisions.emplace(output.get_element_type()); + } + if (auto sub_graph_node = std::dynamic_pointer_cast(node)) + { + if (auto sub_graph = sub_graph_node->get_function()) + { + auto sub_graph_precisions = find_all_used_precisions(sub_graph); + used_precisions.insert(sub_graph_precisions.begin(), + sub_graph_precisions.end()); + } + } + }); + + return used_precisions; + } + +} // namespace + NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertPrecision, "ConvertPrecision", 0); bool ngraph::pass::ConvertPrecision::run_on_function(std::shared_ptr f) @@ -161,117 +349,25 @@ bool ngraph::pass::ConvertPrecision::run_on_function(std::shared_ptr, std::vector>> - const_to_internal_output; + bool is_changed = false; - std::function&)> register_constants = - [&const_to_internal_output](const std::shared_ptr& f) { - for (auto& node : f->get_ordered_ops()) - { - for (auto& input : node->inputs()) - { - if (auto const_node = std::dynamic_pointer_cast( - input.get_source_output().get_node_shared_ptr())) - { - const_to_internal_output[const_node].emplace_back(input); - } - } - } - }; + auto const used_precisions = find_all_used_precisions(f); - auto convert_node_output_precision = [this, &const_to_internal_output, &type_to_fuse]( - const std::shared_ptr& node) { - for (auto output : node->outputs()) - { - if (output.get_element_type() == m_from) - { - // Handle case with Constants as they can have consumers from other nGraph Function - // object - if (ngraph::op::is_constant(node) && const_to_internal_output.count(node)) - { - fuse_type_to_constant(node, m_to, const_to_internal_output.at(node)); - break; - } - - // Check that node type exists in map and we can fuse type into node - if (type_to_fuse.count(node->get_type_info()) && - type_to_fuse.at(node->get_type_info())(node, m_to, output.get_index())) - { - // We need to break if original node was replaced - break; - } - } - } - }; - - auto convert_node_input_precision = [this](const std::shared_ptr& node) { - for (auto input : node->inputs()) - { - if (input.get_element_type() == m_from) - { - // For some operations we need to extend their input types to support new type - if (type_to_extend.count(node->get_type_info()) && - type_to_extend.at(node->get_type_info())(node, m_to, input.get_index())) - { - break; - } - } - } - }; - - std::function&)> convert_function_precision = - [this, - ®ister_constants, - &convert_node_output_precision, - &convert_node_input_precision, - &convert_function_precision](const std::shared_ptr& f) { - // Iterate over all nodes in topological order and then iterate over node outputs. - // If output type mismatch given type we try to fuse type into this operation - // otherwise we insert Convert operation. - for (auto& node : f->get_ordered_ops()) - { - transformation_callback(node); - // Recursively apply transformation for sub-graph based operations - if (auto sub_graph_node = std::dynamic_pointer_cast(node)) - { - if (auto sub_graph = sub_graph_node->get_function()) - { - convert_function_precision(sub_graph); - } - } - convert_node_input_precision(node); - } - // Register internal constants only after fixing input type that could lead to nodes - // replacement - register_constants(f); - - for (auto& node : f->get_ordered_ops()) - { - convert_node_output_precision(node); - } - }; - - convert_function_precision(f); - f->validate_nodes_and_infer_types(); - - // TODO: we need to split NopElimination pass to separate MatcherPasses and call Convert - // elimination here - for (auto& node : f->get_ordered_ops()) + for (auto const& p : m_precisions) { - if (auto convert = std::dynamic_pointer_cast(node)) - { - // WA for topK, dont remove fake convert - if (convert->input(0).get_element_type() == convert->get_convert_element_type() && - convert->input_value(0).get_node_shared_ptr()->get_output_size() == 1) - { - replace_output_update_name(convert->output(0), convert->input_value(0)); - } - } + if (used_precisions.count(p.first)) + is_changed = + is_changed | + convert_precision(*this, f, type_to_fuse, type_to_extend, p.first, p.second); } - return true; + + (void)is_changed; // ignored + + // Returning value is false because pass::Manager always apply Validation pass + // if function was changed. This helps to avoid excess Validations after applying + // this pass. In future when we will return more meaningful status code it will be + // replaced with real status reported by manager.run_passes() method call. + return false; } bool fuse_type_to_shapeof(const std::shared_ptr& node, element::Type to, size_t idx) @@ -532,15 +628,6 @@ namespace return new_constant; } - struct EnumClassHash - { - template - std::size_t operator()(T t) const - { - return static_cast(t); - } - }; - /** * @brief Method converts low precision integer types * The method uses the next logic for conversion: @@ -631,8 +718,8 @@ namespace element::Type to) { // Supported integer precisions - static const std::unordered_set - supported_integer_precisions = {element::i4, element::u4, element::u1}; + static const precisions_set_t supported_integer_precisions = { + element::i4, element::u4, element::u1}; // Get source element type and source data auto src_type = constant->get_element_type(); const auto* src_data = reinterpret_cast(constant->get_data_ptr()); diff --git a/ngraph/test/backend/convert.in.cpp b/ngraph/test/backend/convert.in.cpp index 46159d0cbc2..730fc13cd50 100644 --- a/ngraph/test/backend/convert.in.cpp +++ b/ngraph/test/backend/convert.in.cpp @@ -439,3 +439,22 @@ NGRAPH_TEST(${BACKEND_NAME}, convert_u8_to_u64) ConvertTest(input, input_shape, input_type, expected_output, expected_output_type); } + +NGRAPH_TEST(${BACKEND_NAME}, convert_float32_int8) +{ + std::vector f32vec = {-100.5, -20.5, -15, -10.5, -0.5, 0, 0.5, 10.5, 15, 20.5, 100.5}; + std::vector result(f32vec.size()); + std::vector i8vec(std::begin(f32vec), std::end(f32vec)); + runtime::reference::convert(f32vec.data(), result.data(), f32vec.size()); + EXPECT_EQ(result, i8vec); +} + +NGRAPH_TEST(${BACKEND_NAME}, convert_fp16_int8) +{ + std::vector f32vec = {-100.5, -20.5, -15, -10.5, -0.5, 0, 0.5, 10.5, 15, 20.5, 100.5}; + std::vector f16vec(std::begin(f32vec), std::end(f32vec)); + std::vector i8vec(std::begin(f16vec), std::end(f16vec)); + std::vector result(i8vec.size()); + runtime::reference::convert(f16vec.data(), result.data(), f16vec.size()); + EXPECT_EQ(result, i8vec); +} From 76cc22beb389d5a94c4b19b1e3dba08b2653561f Mon Sep 17 00:00:00 2001 From: Gorokhov Dmitriy Date: Fri, 14 May 2021 15:41:11 +0300 Subject: [PATCH 67/99] Revert "Added MVN fusion for case with constants inside (#4961)" (#5632) This reverts commit 621e36ee7937b22806926ef78013a964b597afd6. --- .../common_optimizations/mvn_fusion.hpp | 32 +---- .../common_optimizations/mvn_fusion.cpp | 116 +----------------- .../transformations/mvn_fusion_test.cpp | 46 ------- 3 files changed, 5 insertions(+), 189 deletions(-) diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/mvn_fusion.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/mvn_fusion.hpp index 6a25a3f00f7..3de28fe67f9 100644 --- a/inference-engine/src/transformations/include/transformations/common_optimizations/mvn_fusion.hpp +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/mvn_fusion.hpp @@ -16,9 +16,7 @@ namespace ngraph { namespace pass { -class TRANSFORMATIONS_API MVNFusion; -class TRANSFORMATIONS_API MVNFusionWithoutConstants; -class TRANSFORMATIONS_API MVNFusionWithConstantsInside; + class TRANSFORMATIONS_API MVNFusion; } // namespace pass } // namespace ngraph @@ -28,32 +26,8 @@ class TRANSFORMATIONS_API MVNFusionWithConstantsInside; * @brief MVNFusion transformation replaces group of * operations: (x - ReduceMean(x, axes)) / (Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2)) + eps) to MVN op. */ -class ngraph::pass::MVNFusionWithoutConstants : public ngraph::pass::MatcherPass { +class ngraph::pass::MVNFusion : public ngraph::pass::MatcherPass { public: NGRAPH_RTTI_DECLARATION; - MVNFusionWithoutConstants(); -}; - -/** - * @ingroup ie_transformation_common_api - * @brief MVNFusion transformation replaces group of - * operations: gamma * (x - ReduceMean(x, axes)) / (Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2)) + eps) - beta to MVN op. - */ -class ngraph::pass::MVNFusionWithConstantsInside : public ngraph::pass::MatcherPass { -public: - NGRAPH_RTTI_DECLARATION; - MVNFusionWithConstantsInside(); -}; - -/** - * @ingroup ie_transformation_common_api - * @brief MVNFusion transformation replaces various sub-graphs with a MVN op. - */ -class ngraph::pass::MVNFusion: public ngraph::pass::GraphRewrite { -public: - NGRAPH_RTTI_DECLARATION; - MVNFusion() { - add_matcher(); - add_matcher(); - } + MVNFusion(); }; diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/mvn_fusion.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/mvn_fusion.cpp index bb0a97c03f0..9ef143a614e 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/mvn_fusion.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/mvn_fusion.cpp @@ -27,10 +27,8 @@ std::function)> value_is_equal_to(const std::v }; } -NGRAPH_RTTI_DEFINITION(ngraph::pass::MVNFusionWithoutConstants, "MVNFusionWithoutConstants", 0); - -ngraph::pass::MVNFusionWithoutConstants::MVNFusionWithoutConstants() { - MATCHER_SCOPE(MVNFusionWithoutConstants); +ngraph::pass::MVNFusion::MVNFusion() { + MATCHER_SCOPE(MVNFusion); // Detect MVN decomposition pattern: // (x - ReduceMean(x, axes)) / (Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2)) + eps) auto x = pattern::any_input(); @@ -190,113 +188,3 @@ ngraph::pass::MVNFusionWithoutConstants::MVNFusionWithoutConstants() { auto m = std::make_shared(powerMulOrDiv, matcher_name); register_matcher(m, matcher_pass_callback); } - -NGRAPH_RTTI_DEFINITION(ngraph::pass::MVNFusionWithConstantsInside, "MVNFusionWithConstantsInside", 0); - -ngraph::pass::MVNFusionWithConstantsInside::MVNFusionWithConstantsInside() { - MATCHER_SCOPE(MVNFusionWithConstantsInside); - // Detect MVN decomposition pattern: - // (x - ReduceMean(x, axes)) * gamma / (Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2)) + eps) - beta - auto x = pattern::any_input(); - - // (x - ReduceMean(x, axes))^2 - // `------mean1-------' - auto mean1_axes = pattern::wrap_type(); - auto mean1 = pattern::wrap_type({ x, mean1_axes }); - - // (x - ReduceMean(x, axes))^2 - // `-squared_difference------' - auto squared_difference = pattern::wrap_type({ x, mean1 }); - - // 1 / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - // `---mean2--------------------------------' - auto mean2_axes = pattern::wrap_type(); - auto mean2 = pattern::wrap_type({ squared_difference, mean2_axes }); - - // 1 / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - // `------------------------------------------add--' - auto eps = pattern::wrap_type(); - auto add_eps = pattern::wrap_type({ mean2, eps }); - - // 1 / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - // `-power-------------------------------------------------' - auto const_0_5 = pattern::wrap_type(value_is_equal_to({-0.5})); - auto power = pattern::wrap_type({ add_eps, const_0_5 }); - - // gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - // `---mul1----------------------------------------------------' - auto gamma = pattern::wrap_type(); - auto mul1 = pattern::wrap_type({ power, gamma }); - - // x * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - // `---mul2--------------------------------------------------------' - auto mul2 = pattern::wrap_type({ x, mul1 }); - - // ReduceMean(x, axes) * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - beta - // `-------------------mul3----------------------------------------------------------' - auto mul3 = pattern::wrap_type({ mul1, mean1 }); - - // beta - ReduceMean(x, axes) * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - // `---sub-----------------------------------------------------------------------------------' - auto beta = pattern::wrap_type(); - auto sub = pattern::wrap_type({ beta, mul3 }); - - // Final Add - // x * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) + - // beta - ReduceMean(x, axes) * gamma / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) = - // gamma * (x - ReduceMean(x, axes)) / Sqrt(ReduceMean((x - ReduceMean(x, axes)) ^ 2) + eps) - beta - auto add = pattern::wrap_type({ mul2, sub }); - - ngraph::matcher_pass_callback matcher_pass_callback = [=](ngraph::pattern::Matcher& m) { - auto& pattern_to_output = m.get_pattern_value_map(); - auto x_output = pattern_to_output.at(x); - - auto const_0_5_node = std::dynamic_pointer_cast(pattern_to_output.at(const_0_5).get_node_shared_ptr()); - if (!const_0_5_node) { - return false; - } - - auto const_gamma_node = std::dynamic_pointer_cast(pattern_to_output.at(gamma).get_node_shared_ptr()); - auto const_beta_node = std::dynamic_pointer_cast(pattern_to_output.at(beta).get_node_shared_ptr()); - auto const_eps_node = std::dynamic_pointer_cast(pattern_to_output.at(eps).get_node_shared_ptr()); - float eps_value; - - bool valid_constant_values = op::util::has_constant_value(const_0_5_node, -0.5) && op::util::get_single_value(const_eps_node, eps_value); - if (!valid_constant_values) { - return false; - } - - auto axes_1_node = std::dynamic_pointer_cast(pattern_to_output.at(mean1_axes).get_node_shared_ptr()); - auto axes_2_node = std::dynamic_pointer_cast(pattern_to_output.at(mean2_axes).get_node_shared_ptr()); - if (!axes_1_node || !axes_2_node) { - return false; - } - - auto axes_1_value = axes_1_node->cast_vector(); - auto axes_2_value = axes_2_node->cast_vector(); - if (axes_1_value != axes_2_value) { - return false; - } - - auto mvn = std::make_shared(x_output, axes_1_node, true, eps_value, op::MVNEpsMode::INSIDE_SQRT); - auto mul_gamma = std::make_shared(mvn, const_gamma_node); - auto add_beta = std::make_shared(mul_gamma, const_beta_node); - - ngraph::copy_runtime_info({ pattern_to_output.at(mean1).get_node_shared_ptr(), - pattern_to_output.at(squared_difference).get_node_shared_ptr(), - pattern_to_output.at(add_eps).get_node_shared_ptr(), - pattern_to_output.at(power).get_node_shared_ptr(), - pattern_to_output.at(mul1).get_node_shared_ptr(), - pattern_to_output.at(mul2).get_node_shared_ptr(), - pattern_to_output.at(mul3).get_node_shared_ptr(), - pattern_to_output.at(sub).get_node_shared_ptr(), - pattern_to_output.at(add).get_node_shared_ptr() }, - { mvn, const_gamma_node, mul_gamma, const_beta_node, add_beta }); - add_beta->set_friendly_name(m.get_match_root()->get_friendly_name()); - ngraph::replace_node(m.get_match_root(), add_beta); - return true; - }; - - auto m = std::make_shared(add, matcher_name); - register_matcher(m, matcher_pass_callback); -} diff --git a/inference-engine/tests/functional/inference_engine/transformations/mvn_fusion_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/mvn_fusion_test.cpp index e45258a63e6..21b2b695454 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/mvn_fusion_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/mvn_fusion_test.cpp @@ -419,49 +419,3 @@ TEST(TransformationTests, MVNFusionTestAltDivInsideSqrt) { auto res = compare_functions(f, f_ref); ASSERT_TRUE(res.first) << res.second; } - -TEST(TransformationTests, MVNFusionTestWithParametersInside) { - std::shared_ptr f(nullptr), f_ref(nullptr); - { - auto input = std::make_shared(ngraph::element::f32, ngraph::Shape{ 1, 3, 224 }); - auto mean1_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 1 }, { 2 }); - auto mean1 = std::make_shared(input, mean1_axes, true); - auto squared_difference = std::make_shared(input, mean1); - auto mean2_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 1 }, { 2 }); - auto mean2 = std::make_shared(squared_difference, mean2_axes, true); - auto eps = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1e-9 }); - auto add_eps = std::make_shared(mean2, eps); - auto const_0_5 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { -0.5 }); - auto power_sqrt = std::make_shared(add_eps, const_0_5); - auto gamma = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1 }); - auto mul_gamma = std::make_shared(power_sqrt, gamma); - auto mul1 = std::make_shared(input, mul_gamma); - auto mul2 = std::make_shared(mul_gamma, mean1); - auto beta = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { -1 }); - auto sub = std::make_shared(beta, mul2); - auto add = std::make_shared(mul1, sub); - - f = std::make_shared(ngraph::NodeVector{ add }, ngraph::ParameterVector{ input }); - - ngraph::pass::Manager manager; - manager.register_pass(); - manager.register_pass(); - manager.run_passes(f); - ASSERT_NO_THROW(check_rt_info(f)); - } - - { - auto input = std::make_shared(ngraph::element::f32, ngraph::Shape{ 1, 3, 224 }); - auto axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 1 }, { 2 }); - auto mvn = std::make_shared(input, axes, true, 1e-9, ngraph::op::MVNEpsMode::INSIDE_SQRT); - auto gamma = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1 }); - auto mul_gamma = std::make_shared(mvn, gamma); - auto beta = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { -1 }); - auto add = std::make_shared(mul_gamma, beta); - - f_ref = std::make_shared(ngraph::NodeVector{ add }, ngraph::ParameterVector{ input }); - } - - auto res = compare_functions(f, f_ref); - ASSERT_TRUE(res.first) << res.second; -} From 167aa8eb664a8493837068dabdb69b8d044aec75 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 14 May 2021 16:03:49 +0300 Subject: [PATCH 68/99] Added custom versiob of find_dependency (#5628) --- .../templates/InferenceEngineConfig.cmake.in | 55 ++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/inference-engine/cmake/templates/InferenceEngineConfig.cmake.in b/inference-engine/cmake/templates/InferenceEngineConfig.cmake.in index e01e78c1edb..06ef59767d5 100644 --- a/inference-engine/cmake/templates/InferenceEngineConfig.cmake.in +++ b/inference-engine/cmake/templates/InferenceEngineConfig.cmake.in @@ -19,7 +19,36 @@ @PACKAGE_INIT@ -include(CMakeFindDependencyMacro) +macro(_ie_find_dependency dep) + set(cmake_fd_quiet_arg) + if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + set(cmake_fd_quiet_arg QUIET) + endif() + set(cmake_fd_required_arg) + if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + set(cmake_fd_required_arg REQUIRED) + endif() + + get_property(cmake_fd_alreadyTransitive GLOBAL PROPERTY + _CMAKE_${dep}_TRANSITIVE_DEPENDENCY) + + find_package(${dep} ${ARGN} + ${cmake_fd_quiet_arg} + ${cmake_fd_required_arg}) + + if(NOT DEFINED cmake_fd_alreadyTransitive OR cmake_fd_alreadyTransitive) + set_property(GLOBAL PROPERTY _CMAKE_${dep}_TRANSITIVE_DEPENDENCY TRUE) + endif() + + if(NOT ${dep}_FOUND) + set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "${CMAKE_FIND_PACKAGE_NAME} could not be found because dependency ${dep} could not be found.") + set(${CMAKE_FIND_PACKAGE_NAME}_FOUND False) + return() + endif() + + set(cmake_fd_required_arg) + set(cmake_fd_quiet_arg) +endmacro() # need to store current PACKAGE_PREFIX_DIR, because it's overwritten by ngraph one set(IE_PACKAGE_PREFIX_DIR "${PACKAGE_PREFIX_DIR}") @@ -27,21 +56,21 @@ set(IE_PACKAGE_PREFIX_DIR "${PACKAGE_PREFIX_DIR}") set(THREADING "@THREADING@") if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") set_and_check(_tbb_dir "@PACKAGE_IE_TBB_DIR@") - find_dependency(TBB - COMPONENTS tbb tbbmalloc - CONFIG - PATHS ${TBBROOT}/cmake - ${_tbb_dir} - NO_CMAKE_FIND_ROOT_PATH - NO_DEFAULT_PATH) + _ie_find_dependency(TBB + COMPONENTS tbb tbbmalloc + CONFIG + PATHS ${TBBROOT}/cmake + ${_tbb_dir} + NO_CMAKE_FIND_ROOT_PATH + NO_DEFAULT_PATH) endif() set_and_check(_ngraph_dir "@PACKAGE_IE_NGRAPH_DIR@") -find_dependency(ngraph - CONFIG - PATHS ${_ngraph_dir} - NO_CMAKE_FIND_ROOT_PATH - NO_DEFAULT_PATH) +_ie_find_dependency(ngraph + CONFIG + PATHS ${_ngraph_dir} + NO_CMAKE_FIND_ROOT_PATH + NO_DEFAULT_PATH) function(_ie_target_no_deprecation_error) if(NOT MSVC) From 3e076a88aa6b4f911883007929f66971f5851d46 Mon Sep 17 00:00:00 2001 From: Ilya Naumov Date: Fri, 14 May 2021 16:05:25 +0300 Subject: [PATCH 69/99] Align MO pip requirements (#5171) * Align MO pip requirements * fix missing mxnet on platforms other than Windows or Linux * remove spaces near environment markers --- .../prepare_model/Config_Model_Optimizer.md | 4 +++- model-optimizer/requirements.txt | 20 +++++++++---------- model-optimizer/requirements_caffe.txt | 10 +++++----- model-optimizer/requirements_kaldi.txt | 8 ++++---- model-optimizer/requirements_mxnet.txt | 13 ++++++------ model-optimizer/requirements_onnx.txt | 10 +++++----- model-optimizer/requirements_tf.txt | 12 +++++------ model-optimizer/requirements_tf2.txt | 10 +++++----- 8 files changed, 45 insertions(+), 42 deletions(-) diff --git a/docs/MO_DG/prepare_model/Config_Model_Optimizer.md b/docs/MO_DG/prepare_model/Config_Model_Optimizer.md index cced8949e54..9b978d750aa 100644 --- a/docs/MO_DG/prepare_model/Config_Model_Optimizer.md +++ b/docs/MO_DG/prepare_model/Config_Model_Optimizer.md @@ -122,10 +122,12 @@ virtualenv -p /usr/bin/python3.6 .env3 --system-site-packages virtualenv -p /usr/bin/python3.6 .env3/bin/activate ``` 3. Install all dependencies or only the dependencies for a specific framework: - * To install dependencies for all frameworks except TensorFlow* 2.x: + * To install dependencies for all frameworks except TensorFlow* 1.x: ```shell pip3 install -r requirements.txt ``` +> **NOTE**: TensorFlow 1.x and 2.x are incompatible. Use separate virtual environments if you want to install multiple TensorFlow versions. + * To install dependencies only for Caffe: ```shell pip3 install -r requirements_caffe.txt diff --git a/model-optimizer/requirements.txt b/model-optimizer/requirements.txt index f4690746c79..fad2ef68a89 100644 --- a/model-optimizer/requirements.txt +++ b/model-optimizer/requirements.txt @@ -1,10 +1,10 @@ -tensorflow>=1.15.2,<2.0; python_version < "3.8" -tensorflow>=2.2; python_version >= "3.8" -mxnet>=1.0.0,<=1.7.0 -networkx>=1.11 -numpy>=1.14.0,<1.19.0 -protobuf>=3.6.1 -onnx>=1.1.2 -defusedxml>=0.5.0 -urllib3>=1.25.9 -requests>=2.20.0 +tensorflow~=2.4.1 +mxnet~=1.2.0; sys_platform == 'win32' +mxnet~=1.7.0.post2; sys_platform != 'win32' +networkx~=2.5 +numpy~=1.19.5 +protobuf>=3.15.6 +onnx>=1.8.1 +defusedxml>=0.7.1 +urllib3>=1.26.4 +requests>=2.25.1 diff --git a/model-optimizer/requirements_caffe.txt b/model-optimizer/requirements_caffe.txt index 037f0a838f6..f66bcf351d3 100644 --- a/model-optimizer/requirements_caffe.txt +++ b/model-optimizer/requirements_caffe.txt @@ -1,5 +1,5 @@ -networkx>=1.11 -numpy>=1.14.0 -protobuf>=3.6.1 -defusedxml>=0.5.0 -requests>=2.20.0 +networkx~=2.5 +numpy~=1.19.5 +protobuf>=3.15.6 +defusedxml>=0.7.1 +requests>=2.25.1 diff --git a/model-optimizer/requirements_kaldi.txt b/model-optimizer/requirements_kaldi.txt index b027c76c594..d941609bd09 100644 --- a/model-optimizer/requirements_kaldi.txt +++ b/model-optimizer/requirements_kaldi.txt @@ -1,4 +1,4 @@ -networkx>=1.11 -numpy>=1.14.0 -defusedxml>=0.5.0 -requests>=2.20.0 +networkx~=2.5 +numpy~=1.19.5 +defusedxml>=0.7.1 +requests>=2.25.1 diff --git a/model-optimizer/requirements_mxnet.txt b/model-optimizer/requirements_mxnet.txt index 8877c2b499e..a5def5cf31a 100644 --- a/model-optimizer/requirements_mxnet.txt +++ b/model-optimizer/requirements_mxnet.txt @@ -1,6 +1,7 @@ -mxnet>=1.0.0,<=1.7.0 -networkx>=1.11 -numpy>=1.14.0 -defusedxml>=0.5.0 -urllib3>=1.25.9 -requests>=2.20.0 +mxnet~=1.2.0; sys_platform == 'win32' +mxnet~=1.7.0.post2; sys_platform != 'win32' +networkx~=2.5 +numpy~=1.19.5 +defusedxml>=0.7.1 +urllib3>=1.26.4 +requests>=2.25.1 diff --git a/model-optimizer/requirements_onnx.txt b/model-optimizer/requirements_onnx.txt index 29730df249b..f5ccc126293 100644 --- a/model-optimizer/requirements_onnx.txt +++ b/model-optimizer/requirements_onnx.txt @@ -1,5 +1,5 @@ -onnx>=1.1.2 -networkx>=1.11 -numpy>=1.14.0 -defusedxml>=0.5.0 -requests>=2.20.0 +onnx>=1.8.1 +networkx~=2.5 +numpy~=1.19.5 +defusedxml>=0.7.1 +requests>=2.25.1 diff --git a/model-optimizer/requirements_tf.txt b/model-optimizer/requirements_tf.txt index 3a83569827d..7d5404a0134 100644 --- a/model-optimizer/requirements_tf.txt +++ b/model-optimizer/requirements_tf.txt @@ -1,6 +1,6 @@ -tensorflow>=1.15.2,<2.0; python_version < "3.8" -tensorflow>=2.2; python_version >= "3.8" -networkx>=1.11 -numpy>=1.14.0,<1.19.0 -defusedxml>=0.5.0 -requests>=2.20.0 +# TensorFlow 1.x and 2.x are incompatible, use separate virtual environments for each version +tensorflow~=1.15.5 +networkx~=2.5 +numpy~=1.18.5 +defusedxml>=0.7.1 +requests>=2.25.1 diff --git a/model-optimizer/requirements_tf2.txt b/model-optimizer/requirements_tf2.txt index 94497c8a32a..2247103ad99 100644 --- a/model-optimizer/requirements_tf2.txt +++ b/model-optimizer/requirements_tf2.txt @@ -1,5 +1,5 @@ -tensorflow>=2.2 -networkx>=1.11 -numpy>=1.14.0 -defusedxml>=0.5.0 -requests>=2.20.0 +tensorflow~=2.4.1 +networkx~=2.5 +numpy~=1.19.5 +defusedxml>=0.7.1 +requests>=2.25.1 From e8eebf4cccc6e8a7f2165535413fcc45d6fbf1be Mon Sep 17 00:00:00 2001 From: Ilya Naumov Date: Fri, 14 May 2021 16:05:38 +0300 Subject: [PATCH 70/99] Align pip requirements of benchmark tool, cross check tool, IE Python API (#5199) * align pypi deps of benchmark, cross check tool, python API * move cython from python API requirements to requirements-dev * change requirements to >= for most packages * update requirements * set pinned numpy major version in wheel requirements * set more strict pip requirements-dev in wheel * change scikit-image version to 0.17 --- .../ie_bridges/python/requirements.txt | 3 +- .../python/src/requirements-dev.txt | 1 + .../wheel/meta/openvino-dev.requirements.txt | 48 +++++++++---------- .../wheel/meta/openvino.requirements.txt | 2 +- .../tools/benchmark_tool/requirements.txt | 8 ++-- .../tools/cross_check_tool/requirements.txt | 4 +- tools/benchmark/requirements.txt | 8 ++-- 7 files changed, 37 insertions(+), 37 deletions(-) diff --git a/inference-engine/ie_bridges/python/requirements.txt b/inference-engine/ie_bridges/python/requirements.txt index 2789db52718..a8631bee246 100644 --- a/inference-engine/ie_bridges/python/requirements.txt +++ b/inference-engine/ie_bridges/python/requirements.txt @@ -1,2 +1 @@ -numpy>=1.16.3 -cython>=0.29.17 +numpy~=1.19.5 \ No newline at end of file diff --git a/inference-engine/ie_bridges/python/src/requirements-dev.txt b/inference-engine/ie_bridges/python/src/requirements-dev.txt index 00c455c2c62..8096521bccd 100644 --- a/inference-engine/ie_bridges/python/src/requirements-dev.txt +++ b/inference-engine/ie_bridges/python/src/requirements-dev.txt @@ -2,3 +2,4 @@ opencv-python>=3.4.4.19 pytest==4.0.1 attrs==19.1.0 pytest-html==1.19.0 +cython>=0.29.22 \ No newline at end of file diff --git a/inference-engine/ie_bridges/python/wheel/meta/openvino-dev.requirements.txt b/inference-engine/ie_bridges/python/wheel/meta/openvino-dev.requirements.txt index bc34674c2bd..bcbf66e1375 100644 --- a/inference-engine/ie_bridges/python/wheel/meta/openvino-dev.requirements.txt +++ b/inference-engine/ie_bridges/python/wheel/meta/openvino-dev.requirements.txt @@ -1,28 +1,28 @@ -defusedxml>=0.5.0 -scipy==1.5.4 -jstyleson==0.0.2 -numpy~=1.18.5 -addict==2.2.1 +defusedxml>=0.7.1 +scipy~=1.5.4 +jstyleson~=0.0.2 +numpy~=1.19.5 +addict>=2.4.0 pandas~=1.1.5 -hyperopt==0.1.2 -networkx==2.2 -tqdm==4.31.1 -texttable==1.6.3 -py-cpuinfo!=5.0,!=6.0 +hyperopt~=0.1.2 +networkx~=2.5 +tqdm>=4.54.1 +texttable~=1.6.3 +py-cpuinfo>=7.0.0 PyYAML>=5.4.1 -pillow>=8.1.0 -scikit-image>=0.17 -scikit-learn>=0.23 +pillow>=8.1.2 +scikit-image~=0.17.2 +scikit-learn>=0.24.1 yamlloader>=0.5 -shapely>=1.7 -nibabel>=3.1 -pydicom>=2.0 -sentencepiece>=0.1.91 -tokenizers>=0.8 -editdistance>=0.5 -parasail>=1.2 -fast-ctc-decode>=0.2 -rawpy>=0.15 +shapely>=1.7.1 +nibabel>=3.2.1 +pydicom>=2.1.2 +sentencepiece>=0.1.95 +tokenizers>=0.10.1 +editdistance>=0.5.3 +parasail>=1.2.4 +fast-ctc-decode>=0.2.5 +rawpy>=0.16.0 nltk>=3.5 -opencv-python>=4.4 -progress==1.5 +opencv-python==4.5.* +progress>=1.5 diff --git a/inference-engine/ie_bridges/python/wheel/meta/openvino.requirements.txt b/inference-engine/ie_bridges/python/wheel/meta/openvino.requirements.txt index bd5ec2b7680..a8631bee246 100644 --- a/inference-engine/ie_bridges/python/wheel/meta/openvino.requirements.txt +++ b/inference-engine/ie_bridges/python/wheel/meta/openvino.requirements.txt @@ -1 +1 @@ -numpy>=1.16.3 \ No newline at end of file +numpy~=1.19.5 \ No newline at end of file diff --git a/inference-engine/tools/benchmark_tool/requirements.txt b/inference-engine/tools/benchmark_tool/requirements.txt index 7042cb2a066..cec7a6be627 100644 --- a/inference-engine/tools/benchmark_tool/requirements.txt +++ b/inference-engine/tools/benchmark_tool/requirements.txt @@ -1,4 +1,4 @@ -py-cpuinfo -numpy -progress -opencv-python \ No newline at end of file +py-cpuinfo>=7.0.0 +numpy~=1.19.5 +progress>=1.5 +opencv-python==4.5.* \ No newline at end of file diff --git a/inference-engine/tools/cross_check_tool/requirements.txt b/inference-engine/tools/cross_check_tool/requirements.txt index fc4586c8b30..cc5fcac23d3 100644 --- a/inference-engine/tools/cross_check_tool/requirements.txt +++ b/inference-engine/tools/cross_check_tool/requirements.txt @@ -1,2 +1,2 @@ -numpy -opencv-python \ No newline at end of file +numpy~=1.19.5 +opencv-python==4.5.* \ No newline at end of file diff --git a/tools/benchmark/requirements.txt b/tools/benchmark/requirements.txt index 7042cb2a066..cec7a6be627 100644 --- a/tools/benchmark/requirements.txt +++ b/tools/benchmark/requirements.txt @@ -1,4 +1,4 @@ -py-cpuinfo -numpy -progress -opencv-python \ No newline at end of file +py-cpuinfo>=7.0.0 +numpy~=1.19.5 +progress>=1.5 +opencv-python==4.5.* \ No newline at end of file From 8c0f24d4bd78d40befaca2a32a47cd88fe5fb3c6 Mon Sep 17 00:00:00 2001 From: Ivan Kochin Date: Fri, 14 May 2021 16:21:37 +0300 Subject: [PATCH 71/99] Remove temporary CMake solution and use updated tbbbind_2_4 package (#5598) * Remove temporary cmake solution and use updated tbbbind_2_4 package * Remove testing version of dependency * Add versioning Co-authored-by: Kochin, Ivan --- inference-engine/cmake/dependencies.cmake | 8 ++++---- inference-engine/src/inference_engine/CMakeLists.txt | 5 ----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/inference-engine/cmake/dependencies.cmake b/inference-engine/cmake/dependencies.cmake index d0a13a04b50..a9261df7964 100644 --- a/inference-engine/cmake/dependencies.cmake +++ b/inference-engine/cmake/dependencies.cmake @@ -145,10 +145,10 @@ if (THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") ENVIRONMENT "TBBROOT" SHA256 "f1c9b9e2861efdaa01552bd25312ccbc5feeb45551e5f91ae61e29221c5c1479") RESOLVE_DEPENDENCY(TBBBIND_2_4 - ARCHIVE_WIN "tbbbind_2_4_static_win.zip" + ARCHIVE_WIN "tbbbind_2_4_static_win_v2.zip" TARGET_PATH "${TEMP}/tbbbind_2_4" ENVIRONMENT "TBBBIND_2_4_ROOT" - SHA256 "1a3a05082cc5ef1a764d635793be347b82c795f0e9ced771515fc3706a4dc4f0") + SHA256 "90dc165652f6ac2ed3014c71e57f797fcc4b11e1498a468e3d2c85deb2a4186a") elseif(ANDROID) # Should be before LINUX due LINUX is detected as well RESOLVE_DEPENDENCY(TBB ARCHIVE_ANDROID "tbb2020_20200404_android.tgz" @@ -161,9 +161,9 @@ if (THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") TARGET_PATH "${TEMP}/tbb" SHA256 "95b2f3b0b70c7376a0c7de351a355c2c514b42c4966e77e3e34271a599501008") RESOLVE_DEPENDENCY(TBBBIND_2_4 - ARCHIVE_LIN "tbbbind_2_4_static_lin.tgz" + ARCHIVE_LIN "tbbbind_2_4_static_lin_v2.tgz" TARGET_PATH "${TEMP}/tbbbind_2_4" - SHA256 "888582a94f81821f9894cc089db36d5a6c2e0b6998cfa1fec0c027f28c597ada") + SHA256 "6dc926258c6cd3cba0f5c2cc672fd2ad599a1650fe95ab11122e8f361a726cb6") elseif(LINUX AND AARCH64) RESOLVE_DEPENDENCY(TBB ARCHIVE_LIN "keembay/tbb2020_38404_kmb_lic.tgz" diff --git a/inference-engine/src/inference_engine/CMakeLists.txt b/inference-engine/src/inference_engine/CMakeLists.txt index dfb306ad2fb..99dfa1b6401 100644 --- a/inference-engine/src/inference_engine/CMakeLists.txt +++ b/inference-engine/src/inference_engine/CMakeLists.txt @@ -8,11 +8,6 @@ if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") find_package(TBBBIND_2_4 QUIET) if (TBBBIND_2_4_FOUND) message(STATUS "Static tbbbind_2_4 package was found") - - # WA: need to update TBBBind_2_4 package - set_target_properties(TBBbind::tbbbind_2_4 PROPERTIES - MAP_IMPORTED_CONFIG_MINSIZEREL Release - MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release) endif() endif() From a810db0302621172b21b1084a97bd991b78750f4 Mon Sep 17 00:00:00 2001 From: Ilya Naumov Date: Fri, 14 May 2021 17:48:27 +0300 Subject: [PATCH 72/99] Set more strict requirements for IE python samples (#5223) * set more strict requirements for IE python samples * change opencv-python requirement to >= * set opencv-python requirement to 4.5.x.x --- inference-engine/ie_bridges/python/sample/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inference-engine/ie_bridges/python/sample/requirements.txt b/inference-engine/ie_bridges/python/sample/requirements.txt index 6f93dbf487f..399ae04c5f5 100644 --- a/inference-engine/ie_bridges/python/sample/requirements.txt +++ b/inference-engine/ie_bridges/python/sample/requirements.txt @@ -1,2 +1,2 @@ -opencv-python>=3.4.4.19 -numpy>=1.16.3 +opencv-python==4.5.* +numpy~=1.19.5 From addf7dc1e0d79ee5ae309e96c04a6d96d47f3a3c Mon Sep 17 00:00:00 2001 From: Sergey Lyubimtsev Date: Fri, 14 May 2021 18:02:35 +0300 Subject: [PATCH 73/99] remove package_data and entry_points (#5635) --- .../python/wheel/meta/openvino-dev.setup.cfg | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/inference-engine/ie_bridges/python/wheel/meta/openvino-dev.setup.cfg b/inference-engine/ie_bridges/python/wheel/meta/openvino-dev.setup.cfg index 831bea48ee8..d6789c4a084 100644 --- a/inference-engine/ie_bridges/python/wheel/meta/openvino-dev.setup.cfg +++ b/inference-engine/ie_bridges/python/wheel/meta/openvino-dev.setup.cfg @@ -8,20 +8,10 @@ py_modules = mo_kaldi [options.package_data] - mo = *.txt - compression.configs.hardware = *.json - mo.extensions.front.mxnet = *.json - mo.extensions.front.onnx = *.json - mo.extensions.front.tf = *.json - mo.mo.front.caffe.proto = *.proto + * = * [options.entry_points] console_scripts = - mo=mo.__main__:main - pot=app.run:main - accuracy_check=accuracy_checker.main:main - convert_annotation=accuracy_checker.annotation_converters.convert:main - benchmark_app=openvino.tools.benchmark.main:main [metadata] license_files = From 500b922457debe27fa41c3befd2b3f86987b93a3 Mon Sep 17 00:00:00 2001 From: Gleb Kazantaev Date: Fri, 14 May 2021 18:47:13 +0300 Subject: [PATCH 74/99] Set default InitConstMask treshold to zero (#5515) --- .../src/offline_transformations/include/pruning.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inference-engine/src/offline_transformations/include/pruning.hpp b/inference-engine/src/offline_transformations/include/pruning.hpp index c16433685a8..f398ab1713f 100644 --- a/inference-engine/src/offline_transformations/include/pruning.hpp +++ b/inference-engine/src/offline_transformations/include/pruning.hpp @@ -32,7 +32,7 @@ class ngraph::pass::InitConstMask : public ngraph::pass::MatcherPass { public: NGRAPH_RTTI_DECLARATION; explicit InitConstMask(const ngraph::AxisSet & dims, - const std::function & condition = [](const double & value) { return value < 1e-5; }); + const std::function & condition = [](const double & value) { return value == 0; }); }; /** From a3448032caa15ca583f515a992280bb3b61a8a66 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 14 May 2021 18:47:54 +0300 Subject: [PATCH 75/99] Minimized legacy usage in tests (#5591) * Minimized legacy usage in tests * Use legacy only for specific files * Fixed code style * Fixed linkage * Removed old CPU / GPU tests binaries * Test * Disabled IB console * Disabled test for AUTO QueryNetwork from parallel threads --- .ci/azure/windows.yml | 2 +- .../tests/functional/CMakeLists.txt | 2 +- .../inference_engine/CMakeLists.txt | 15 ++ .../inference_engine/caching_test.cpp | 3 +- .../inference_engine/core_threading_tests.cpp | 13 +- .../ngraph_reader/constant_tests.cpp | 16 +- .../ngraph_reader/custom_op_tests.cpp | 60 +++---- .../ngraph_reader/einsum_tests.cpp | 1 - .../ngraph_reader/fake_quantize_tests.cpp | 6 - .../{ => ngraph_reader}/net_reader_test.cpp | 2 +- .../ngraph_reader}/network_utils.cpp | 3 +- .../ngraph_reader}/network_utils.hpp | 1 - .../ngraph_reader/ngraph_reader_tests.hpp | 2 +- .../non_max_suppression_tests.cpp | 2 - .../ngraph_reader/relu_tests.cpp | 6 - .../ngraph_reader/tensor_names.cpp | 2 + .../inference_engine/ngraph_reshape_tests.cpp | 11 -- .../convert_ngraph_to_cnn_network_tests.cpp | 0 .../convert_ti_to_sequences_test.cpp | 1 - .../depth_to_space_fusion_test.cpp | 1 - .../keep_constant_inputs_tests.cpp | 1 + .../optimize_strided_slice_test.cpp | 2 - .../transformations/unroll_loop_test.cpp | 1 - .../unroll_tensor_iterator_test.cpp | 1 - .../tests/functional/plugin/CMakeLists.txt | 1 - .../functional/plugin/cpu/CMakeLists.txt | 5 + .../plugin/cpu/extension/extension.cpp | 148 ++++++++--------- .../skip_tests_config.cpp | 3 + .../cpu/test_utils/fusing_test_utils.hpp | 4 +- .../functional/plugin/gna/CMakeLists.txt | 10 +- .../import_export_memory_layer.cpp | 2 + .../functional/plugin/gpu/CMakeLists.txt | 16 ++ .../layer_transformation.cpp | 5 +- .../conversions/dynamic_shape_resolver.cpp | 1 - .../functional/plugin/shared/CMakeLists.txt | 7 +- .../include/behavior/core_threading_tests.hpp | 4 +- .../include/behavior/exec_graph_info.hpp | 156 ++++++------------ .../shared/include/behavior/test_plugin.hpp | 11 -- .../shared/src/behavior/caching_tests.cpp | 2 +- .../network_serializer.cpp | 92 ----------- .../num_inputs_fusing_bin_conv.cpp | 68 ++------ .../unique_node_names.cpp | 44 ++--- .../depth_to_space_transformation.cpp | 1 - .../layer_transformation.cpp | 1 + .../conv_bias_fusion.cpp | 27 ++- .../shared_test_classes/CMakeLists.txt | 7 +- .../layer_transformation.hpp | 2 - .../single_layer/eltwise.hpp | 1 - .../single_layer/reduce_ops.hpp | 1 - .../layer_transformation.cpp | 2 - .../src/single_layer/gru_sequence.cpp | 1 + .../src/single_layer/prior_box_clustered.cpp | 1 - .../src/subgraph/split_concat_memory.cpp | 1 - .../common_test_utils/CMakeLists.txt | 15 +- .../common_layers_params.cpp | 14 -- .../common_layers_params.hpp | 5 - .../common_test_utils/common_utils.cpp | 40 +++++ .../common_test_utils/common_utils.hpp | 33 ++-- .../functional_test_utils/CMakeLists.txt | 3 + .../src/layer_test_utils/summary.cpp | 3 + .../unit_test_utils/CMakeLists.txt | 3 + .../ie_test_utils/unit_test_utils/empty.cpp | 22 --- .../ie_test_utils/unit_test_utils/mock.cpp | 65 ++++++++ .../mocks/mock_icnn_network.hpp | 7 +- .../mocks/mock_not_empty_icnn_network.hpp | 40 +---- .../src/reshape_fully_connected_function.cpp | 1 - .../functional/CMakeLists.txt | 8 - .../functional/cldnn/CMakeLists.txt | 7 - .../functional/cldnn/dummy.cpp | 4 - .../functional/mkldnn/CMakeLists.txt | 7 - .../functional/mkldnn/dummy.cpp | 3 - .../single_layer_tests.hpp | 1 + 72 files changed, 439 insertions(+), 620 deletions(-) rename inference-engine/tests/functional/inference_engine/{ => ngraph_reader}/net_reader_test.cpp (99%) rename inference-engine/tests/{ie_test_utils/functional_test_utils/src => functional/inference_engine/ngraph_reader}/network_utils.cpp (99%) rename inference-engine/tests/{ie_test_utils/functional_test_utils/include/functional_test_utils => functional/inference_engine/ngraph_reader}/network_utils.hpp (91%) rename inference-engine/tests/functional/inference_engine/{cnn_network => transformations}/convert_ngraph_to_cnn_network_tests.cpp (100%) rename inference-engine/tests/functional/inference_engine/{ => transformations}/keep_constant_inputs_tests.cpp (98%) delete mode 100644 inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/network_serializer.cpp create mode 100644 inference-engine/tests/ie_test_utils/common_test_utils/common_utils.cpp delete mode 100644 inference-engine/tests/ie_test_utils/unit_test_utils/empty.cpp create mode 100644 inference-engine/tests/ie_test_utils/unit_test_utils/mock.cpp delete mode 100644 inference-engine/tests_deprecated/functional/cldnn/CMakeLists.txt delete mode 100644 inference-engine/tests_deprecated/functional/cldnn/dummy.cpp delete mode 100644 inference-engine/tests_deprecated/functional/mkldnn/CMakeLists.txt delete mode 100644 inference-engine/tests_deprecated/functional/mkldnn/dummy.cpp diff --git a/.ci/azure/windows.yml b/.ci/azure/windows.yml index 0ae20539c9b..d029cae6fd0 100644 --- a/.ci/azure/windows.yml +++ b/.ci/azure/windows.yml @@ -163,7 +163,7 @@ jobs: - script: | set PATH=$(TEST_ENV_PATH) rem $(BIN_DIR)\cpuFuncTests.exe --gtest_filter=*smoke* --gtest_output=xml:TEST-cpuFuncTests.xml - "$(IB_TESTCONSOLE)" $(BIN_DIR)\cpuFuncTests.exe --gtest_filter=*smoke*:-*CompareWithRefs/base_size=16_pre_nms_topn=100_post_nms_topn=100_nms_thresh=0.7_feat_stride=1_min_size=1_ratio* --gtest_output=xml:TEST-cpuFuncTests-IB.xml /testlevel=24 + $(BIN_DIR)\cpuFuncTests.exe --gtest_filter=*smoke*:-*CompareWithRefs/base_size=16_pre_nms_topn=100_post_nms_topn=100_nms_thresh=0.7_feat_stride=1_min_size=1_ratio* --gtest_output=xml:TEST-cpuFuncTests-IB.xml displayName: 'CPU FuncTests - IB' continueOnError: false diff --git a/inference-engine/tests/functional/CMakeLists.txt b/inference-engine/tests/functional/CMakeLists.txt index 7acdc314ad2..fd58c0e2bdb 100644 --- a/inference-engine/tests/functional/CMakeLists.txt +++ b/inference-engine/tests/functional/CMakeLists.txt @@ -3,5 +3,5 @@ # add_subdirectory(shared_test_classes) -add_subdirectory(inference_engine) add_subdirectory(plugin) +add_subdirectory(inference_engine) diff --git a/inference-engine/tests/functional/inference_engine/CMakeLists.txt b/inference-engine/tests/functional/inference_engine/CMakeLists.txt index a63a2ba9fed..e6eefc809af 100644 --- a/inference-engine/tests/functional/inference_engine/CMakeLists.txt +++ b/inference-engine/tests/functional/inference_engine/CMakeLists.txt @@ -58,6 +58,21 @@ ie_faster_build(${TARGET_NAME} PCH PRIVATE "precomp.hpp" ) +# CVS-55343 + +file(GLOB_RECURSE legacy_tests + "${CMAKE_CURRENT_SOURCE_DIR}/transformations/*.cpp" # CVS-55385 + "${CMAKE_CURRENT_SOURCE_DIR}/lp_transformations/*.cpp" # CVS-55376 + "${CMAKE_CURRENT_SOURCE_DIR}/ngraph_reader/*.cpp" # CVS-55365 + "${CMAKE_CURRENT_SOURCE_DIR}/cnn_network/cnn_ngraph_impl_tests.cpp" # CVS-55375 + "${CMAKE_CURRENT_SOURCE_DIR}/core_threading_tests.cpp" # CVS-55257 + "${CMAKE_CURRENT_SOURCE_DIR}/caching_test.cpp" # CVS-55257 + "${CMAKE_CURRENT_SOURCE_DIR}/local_test.cpp" # CVS-55386 + ) + +set_source_files_properties(${legacy_tests} PROPERTIES INCLUDE_DIRECTORIES + $) + include(CMakeParseArguments) # diff --git a/inference-engine/tests/functional/inference_engine/caching_test.cpp b/inference-engine/tests/functional/inference_engine/caching_test.cpp index 396838e7b8e..947733c3f15 100644 --- a/inference-engine/tests/functional/inference_engine/caching_test.cpp +++ b/inference-engine/tests/functional/inference_engine/caching_test.cpp @@ -7,9 +7,11 @@ #include #include #include +#include #include #include +#include "ie_core.hpp" #include "ie_plugin_ptr.hpp" #include "ngraph/function.hpp" #include "details/ie_so_loader.h" @@ -23,7 +25,6 @@ #include "common_test_utils/test_constants.hpp" #include "functional_test_utils/test_model/test_model.hpp" -#include "functional_test_utils/network_utils.hpp" #include "unit_test_utils/mocks/mock_iexecutable_network.hpp" #include "unit_test_utils/mocks/mock_iinfer_request.hpp" diff --git a/inference-engine/tests/functional/inference_engine/core_threading_tests.cpp b/inference-engine/tests/functional/inference_engine/core_threading_tests.cpp index f0182f9d49f..791cb220093 100644 --- a/inference-engine/tests/functional/inference_engine/core_threading_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/core_threading_tests.cpp @@ -20,8 +20,16 @@ #include class CoreThreadingTests : public ::testing::Test { +protected: + std::string modelName = "CoreThreadingTests.xml", weightsName = "CoreThreadingTests.bin"; + public: void SetUp() override { + FuncTestUtils::TestModel::generateTestModel(modelName, weightsName); + } + + void TearDown() override { + CommonTestUtils::removeIRFiles(modelName, weightsName); } void runParallel(std::function func, @@ -138,11 +146,10 @@ TEST_F(CoreThreadingTests, DISABLED_GetAvailableDevices) { // tested function: ReadNetwork, AddExtension TEST_F(CoreThreadingTests, ReadNetwork) { InferenceEngine::Core ie; - auto model = FuncTestUtils::TestModel::convReluNormPoolFcModelFP32; - auto network = ie.ReadNetwork(model.model_xml_str, model.weights_blob); + auto network = ie.ReadNetwork(modelName, weightsName); runParallel([&] () { safeAddExtension(ie); - (void)ie.ReadNetwork(model.model_xml_str, model.weights_blob); + (void)ie.ReadNetwork(modelName, weightsName); }, 100, 12); } diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/constant_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/constant_tests.cpp index fb76a331e23..f88d68f798a 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/constant_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/constant_tests.cpp @@ -3,7 +3,6 @@ // #include -#include #include "ngraph_reader_tests.hpp" using namespace InferenceEngine; @@ -40,18 +39,13 @@ TEST_F(NGraphReaderTests, ReadConstantNetwork) { )V0G0N"; - IE_SUPPRESS_DEPRECATED_START - Core ie; - Blob::Ptr weights; + Core ie; + Blob::Ptr weights; - weights = make_shared_blob(TensorDesc(Precision::U8, {5808}, Layout::C)); - weights->allocate(); + weights = make_shared_blob(TensorDesc(Precision::U8, {5808}, Layout::C)); + weights->allocate(); - auto network = ie.ReadNetwork(model, weights); - auto clonedNetwork = cloneNetwork(network); - auto clonedNet = cloneNet(network); - - IE_SUPPRESS_DEPRECATED_END + auto network = ie.ReadNetwork(model, weights); } TEST_F(NGraphReaderTests, ReadConstantNetworkWithNegativeDimension) { diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/custom_op_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/custom_op_tests.cpp index 70f77e7bf55..8efde583d67 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/custom_op_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/custom_op_tests.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include "ngraph_reader_tests.hpp" @@ -19,7 +18,7 @@ public: m_element_type(element_type), m_shape(shape), m_data(data) { - constructor_validate_and_infer_types(); + constructor_validate_and_infer_types(); } void validate_and_infer_types() override { set_output_type(0, m_element_type, m_shape); @@ -40,30 +39,27 @@ public: ngraph::Shape getShapeAttr() const { return m_shape; } void* getDataPtr() { return (m_data ? m_data->get_ptr() : nullptr); } - private: - ngraph::element::Type m_element_type; - ngraph::Shape m_shape{}; - std::shared_ptr m_data; +private: + ngraph::element::Type m_element_type; + ngraph::Shape m_shape{}; + std::shared_ptr m_data; }; constexpr ngraph::NodeTypeInfo CustomAddConst::type_info; class CustomAddConstExtension : public InferenceEngine::IExtension { - public: - CustomAddConstExtension() { - } +public: + void GetVersion(const InferenceEngine::Version*& versionInfo) const noexcept override {} - void GetVersion(const InferenceEngine::Version*& versionInfo) const noexcept override {} + void Unload() noexcept override {} - void Unload() noexcept override {} - - std::map getOpSets() override { - std::map opsets; - ngraph::OpSet opset; - opset.insert(); - opsets["custom_opset"] = opset; - return opsets; - } + std::map getOpSets() override { + std::map opsets; + ngraph::OpSet opset; + opset.insert(); + opsets["custom_opset"] = opset; + return opsets; + } }; TEST_F(NGraphReaderTests, ReadCustomAddConstNetwork) { @@ -106,26 +102,22 @@ TEST_F(NGraphReaderTests, ReadCustomAddConstNetwork) { )V0G0N"; - std::string expectedValue = std::string("0?|%.g6/,-{5~P1>"); + const std::string expectedValue = std::string("0?|%.g6/,-{5~P1>"); REPLACE_WITH_STR(model, "_VALUE_", expectedValue); InferenceEngine::Blob::CPtr weights; + InferenceEngine::Core ie; ie.AddExtension(std::make_shared()); - auto network = ie.ReadNetwork(model, weights); - IE_SUPPRESS_DEPRECATED_START - auto convertedNetwork = std::make_shared(network); - - for (auto it = details::CNNNetworkIterator(convertedNetwork.get()); it != details::CNNNetworkIterator(); it++) { - InferenceEngine::CNNLayerPtr layer = *it; - ASSERT_NE(nullptr, layer->getNode()); + bool found = false; + for (const auto & op : network.getFunction()->get_ops()) { + if (auto casted = std::dynamic_pointer_cast(op)) { + std::string actualValue(reinterpret_cast(casted->getDataPtr()), + expectedValue.length()); + ASSERT_EQ(expectedValue, actualValue); + found = true; + } } - - InferenceEngine::CNNLayerPtr customAdd; - convertedNetwork->getLayerByName("activation", customAdd, nullptr); - - ASSERT_EQ(expectedValue, customAdd->GetParamAsString("value")); - - IE_SUPPRESS_DEPRECATED_END + ASSERT_TRUE(found); } diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/einsum_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/einsum_tests.cpp index 753aff586cb..16da3327ac5 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/einsum_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/einsum_tests.cpp @@ -4,7 +4,6 @@ #include #include "ngraph_reader_tests.hpp" -#include "common_test_utils/xml_net_builder/ir_net.hpp" TEST_F(NGraphReaderTests, ReadEinsumNetwork) { std::string model = R"V0G0N( diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/fake_quantize_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/fake_quantize_tests.cpp index 1be3cc7f70d..991699c3af6 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/fake_quantize_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/fake_quantize_tests.cpp @@ -255,10 +255,4 @@ TEST_F(NGraphReaderTests, ReadFQNetwork) { Core reader; auto cnn = reader.ReadNetwork(model, weights); - - IE_SUPPRESS_DEPRECATED_START - // convert to old representation - auto convertedNetwork = std::make_shared(cnn); - (void)convertedNetwork; - IE_SUPPRESS_DEPRECATED_END } diff --git a/inference-engine/tests/functional/inference_engine/net_reader_test.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/net_reader_test.cpp similarity index 99% rename from inference-engine/tests/functional/inference_engine/net_reader_test.cpp rename to inference-engine/tests/functional/inference_engine/ngraph_reader/net_reader_test.cpp index e01379ad348..71265bbf66d 100644 --- a/inference-engine/tests/functional/inference_engine/net_reader_test.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/net_reader_test.cpp @@ -14,7 +14,7 @@ #include "common_test_utils/unicode_utils.hpp" #include "common_test_utils/file_utils.hpp" #include "functional_test_utils/test_model/test_model.hpp" -#include "functional_test_utils/network_utils.hpp" +#include "network_utils.hpp" #ifdef ENABLE_UNICODE_PATH_SUPPORT diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/src/network_utils.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/network_utils.cpp similarity index 99% rename from inference-engine/tests/ie_test_utils/functional_test_utils/src/network_utils.cpp rename to inference-engine/tests/functional/inference_engine/ngraph_reader/network_utils.cpp index 91348277147..7894d83f5cd 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/src/network_utils.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/network_utils.cpp @@ -9,10 +9,11 @@ #include #include -#include "functional_test_utils/network_utils.hpp" +#include "network_utils.hpp" #include "cpp/ie_cnn_network.h" #include "functional_test_utils/blob_utils.hpp" #include +#include namespace FuncTestUtils { diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/network_utils.hpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/network_utils.hpp similarity index 91% rename from inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/network_utils.hpp rename to inference-engine/tests/functional/inference_engine/ngraph_reader/network_utils.hpp index b50f52d6043..4cfa2bca7a5 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/network_utils.hpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/network_utils.hpp @@ -6,7 +6,6 @@ #include "cpp/ie_cnn_network.h" #include -#include namespace FuncTestUtils { diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/ngraph_reader_tests.hpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/ngraph_reader_tests.hpp index ab6f7e5b42f..dc8ca7cff05 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/ngraph_reader_tests.hpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/ngraph_reader_tests.hpp @@ -18,7 +18,7 @@ #include "common_test_utils/test_common.hpp" #include "common_test_utils/file_utils.hpp" #include "common_test_utils/data_utils.hpp" -#include "functional_test_utils/network_utils.hpp" +#include "network_utils.hpp" using namespace testing; using namespace InferenceEngine; diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/non_max_suppression_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/non_max_suppression_tests.cpp index 039a3afc1ba..0148c84a5a9 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/non_max_suppression_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/non_max_suppression_tests.cpp @@ -18,8 +18,6 @@ #include "common_test_utils/ngraph_test_utils.hpp" -#include "legacy/convert_function_to_cnn_network.hpp" - using namespace ngraph; TEST_F(NGraphReaderTests, ReadNonMaxSuppression5) { diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/relu_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/relu_tests.cpp index e6bb675637c..cc5fee390e1 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/relu_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/relu_tests.cpp @@ -220,10 +220,4 @@ TEST_F(NGraphReaderTests, ReadReLUScalarNetwork) { Blob::CPtr blob; Core reader; auto cnn = reader.ReadNetwork(model, blob); - - IE_SUPPRESS_DEPRECATED_START - // convert to old representation - auto convertedNetwork = std::make_shared(cnn); - (void)convertedNetwork; - IE_SUPPRESS_DEPRECATED_END } diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/tensor_names.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/tensor_names.cpp index 1710c49116d..b33ab31bd1c 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/tensor_names.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/tensor_names.cpp @@ -3,6 +3,8 @@ // #include +#include + #include "ngraph_reader_tests.hpp" TEST_F(NGraphReaderTests, ReadNetworkWithTensorNames) { diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp index b3b23babf32..761bea6ecdb 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include "common_test_utils/test_common.hpp" @@ -337,10 +336,6 @@ TEST_F(NGraphReshapeTests, ReshapeNewIRWithNewExtension1) { auto output = network.getOutputsInfo(); SizeVector outDims = output["activation"]->getTensorDesc().getDims(); ASSERT_EQ(outDims, refAfterReshape); - // Convert to CNNNetwork - auto convertedNetwork = std::make_shared(network); - auto layer = CommonTestUtils::getLayerByName(InferenceEngine::CNNNetwork(convertedNetwork), "activation"); - ASSERT_EQ("CustomTestLayer", layer->type); } TEST_F(NGraphReshapeTests, ReshapeNewIRWithNewExtension2) { @@ -408,12 +403,6 @@ TEST_F(NGraphReshapeTests, ReshapeNewIRWithNewExtension2) { auto output = network.getOutputsInfo(); SizeVector outDims = output["activation"]->getTensorDesc().getDims(); ASSERT_EQ(outDims, refAfterReshape); - // Convert to CNNNetwork - auto convertedNetwork = std::make_shared(network); - auto layer = CommonTestUtils::getLayerByName(InferenceEngine::CNNNetwork(convertedNetwork), "activation"); - ASSERT_EQ("CustomTestLayer", layer->type); - ASSERT_EQ("false", layer->params["test1"]); - ASSERT_EQ("3", layer->params["test2"]); } class BadExtension : public InferenceEngine::IExtension { diff --git a/inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_ngraph_to_cnn_network_tests.cpp similarity index 100% rename from inference-engine/tests/functional/inference_engine/cnn_network/convert_ngraph_to_cnn_network_tests.cpp rename to inference-engine/tests/functional/inference_engine/transformations/convert_ngraph_to_cnn_network_tests.cpp diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_ti_to_sequences_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_ti_to_sequences_test.cpp index 26fff36c921..3d9135b32e0 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_ti_to_sequences_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_ti_to_sequences_test.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/inference-engine/tests/functional/inference_engine/transformations/depth_to_space_fusion_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/depth_to_space_fusion_test.cpp index 3475f882993..f610708e1b6 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/depth_to_space_fusion_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/depth_to_space_fusion_test.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/inference-engine/tests/functional/inference_engine/keep_constant_inputs_tests.cpp b/inference-engine/tests/functional/inference_engine/transformations/keep_constant_inputs_tests.cpp similarity index 98% rename from inference-engine/tests/functional/inference_engine/keep_constant_inputs_tests.cpp rename to inference-engine/tests/functional/inference_engine/transformations/keep_constant_inputs_tests.cpp index 81bb6dd5ffe..d5ece0a3a61 100644 --- a/inference-engine/tests/functional/inference_engine/keep_constant_inputs_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/keep_constant_inputs_tests.cpp @@ -5,6 +5,7 @@ #include #include #include // deprecated API +#include // deprecated API #include #include diff --git a/inference-engine/tests/functional/inference_engine/transformations/optimize_strided_slice_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/optimize_strided_slice_test.cpp index b8fc20da532..cfe9314880f 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/optimize_strided_slice_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/optimize_strided_slice_test.cpp @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include #include diff --git a/inference-engine/tests/functional/inference_engine/transformations/unroll_loop_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/unroll_loop_test.cpp index 311ea8e1b4e..e07785a0f67 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/unroll_loop_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/unroll_loop_test.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/inference-engine/tests/functional/inference_engine/transformations/unroll_tensor_iterator_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/unroll_tensor_iterator_test.cpp index c4d83b14d4b..8327ae02787 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/unroll_tensor_iterator_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/unroll_tensor_iterator_test.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/inference-engine/tests/functional/plugin/CMakeLists.txt b/inference-engine/tests/functional/plugin/CMakeLists.txt index 0c7d7594d2d..348e59c925f 100644 --- a/inference-engine/tests/functional/plugin/CMakeLists.txt +++ b/inference-engine/tests/functional/plugin/CMakeLists.txt @@ -21,4 +21,3 @@ if (ENABLE_MYRIAD) endif() add_subdirectory(conformance) - diff --git a/inference-engine/tests/functional/plugin/cpu/CMakeLists.txt b/inference-engine/tests/functional/plugin/cpu/CMakeLists.txt index abc6cc8fd8f..e9eeb694ed5 100644 --- a/inference-engine/tests/functional/plugin/cpu/CMakeLists.txt +++ b/inference-engine/tests/functional/plugin/cpu/CMakeLists.txt @@ -30,3 +30,8 @@ addIeTargetTest( LABELS CPU ) + +# CVS-55352 +set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/bfloat16/memory_conv.cpp" + PROPERTIES INCLUDE_DIRECTORIES + $) diff --git a/inference-engine/tests/functional/plugin/cpu/extension/extension.cpp b/inference-engine/tests/functional/plugin/cpu/extension/extension.cpp index 93eb83c4f83..274aba63069 100644 --- a/inference-engine/tests/functional/plugin/cpu/extension/extension.cpp +++ b/inference-engine/tests/functional/plugin/cpu/extension/extension.cpp @@ -8,74 +8,71 @@ #include #include #include -#include #include class CustomAbsKernel : public InferenceEngine::ILayerExecImpl { - public: - explicit CustomAbsKernel(const std::shared_ptr& node): node(node) {} +public: + explicit CustomAbsKernel(const std::shared_ptr& node): node(node) {} - InferenceEngine::StatusCode - init(InferenceEngine::LayerConfig& /*config*/, InferenceEngine::ResponseDesc* /*resp*/) noexcept override { - return InferenceEngine::StatusCode::OK; + InferenceEngine::StatusCode + init(InferenceEngine::LayerConfig& /*config*/, InferenceEngine::ResponseDesc* /*resp*/) noexcept override { + return InferenceEngine::StatusCode::OK; + } + + InferenceEngine::StatusCode getSupportedConfigurations(std::vector& conf, + InferenceEngine::ResponseDesc* /*resp*/) noexcept override { + InferenceEngine::LayerConfig layerConfig; + layerConfig.dynBatchSupport = true; + + if (node->outputs().size() != 1 && node->inputs().size() != 1) + return InferenceEngine::GENERAL_ERROR; + + InferenceEngine::DataConfig cfg; + cfg.constant = false; + cfg.inPlace = 0; + + InferenceEngine::SizeVector order; + auto partialShape = node->get_output_partial_shape(0); + if (partialShape.is_dynamic()) + return InferenceEngine::GENERAL_ERROR; + + auto shape = node->get_output_shape(0); + for (size_t i = 0; i < shape.size(); i++) { + order.push_back(i); } + cfg.desc = InferenceEngine::TensorDesc(InferenceEngine::Precision::FP32, + shape, {shape, order}); + layerConfig.outConfs.push_back(cfg); + layerConfig.inConfs.push_back(cfg); + conf.push_back(layerConfig); + return InferenceEngine::OK; + } - InferenceEngine::StatusCode getSupportedConfigurations(std::vector& conf, - InferenceEngine::ResponseDesc* /*resp*/) noexcept override { - InferenceEngine::LayerConfig layerConfig; - layerConfig.dynBatchSupport = true; - - if (node->outputs().size() != 1 && node->inputs().size() != 1) - return InferenceEngine::GENERAL_ERROR; - - InferenceEngine::DataConfig cfg; - cfg.constant = false; - cfg.inPlace = 0; - - InferenceEngine::SizeVector order; - auto partialShape = node->get_output_partial_shape(0); - if (partialShape.is_dynamic()) - return InferenceEngine::GENERAL_ERROR; - - auto shape = node->get_output_shape(0); - for (size_t i = 0; i < shape.size(); i++) { - order.push_back(i); + InferenceEngine::StatusCode + execute(std::vector& inputs, std::vector& outputs, + InferenceEngine::ResponseDesc* /*resp*/) noexcept override { + for (size_t i = 0; i < inputs.size(); i++) { + InferenceEngine::MemoryBlob::CPtr minput = InferenceEngine::as(inputs[i]); + InferenceEngine::MemoryBlob::Ptr moutput = InferenceEngine::as(outputs[i]); + if (!moutput || !minput) { + return InferenceEngine::StatusCode::PARAMETER_MISMATCH; } - cfg.desc = InferenceEngine::TensorDesc(InferenceEngine::Precision::FP32, - shape, {shape, order}); - layerConfig.outConfs.push_back(cfg); - layerConfig.inConfs.push_back(cfg); - conf.push_back(layerConfig); - return InferenceEngine::OK; - } + // locked memory holder should be alive all time while access to its buffer happens + auto minputHolder = minput->rmap(); + auto moutputHolder = moutput->wmap(); - InferenceEngine::StatusCode - execute(std::vector& inputs, std::vector& outputs, - InferenceEngine::ResponseDesc* /*resp*/) noexcept override { - for (size_t i = 0; i < inputs.size(); i++) { - InferenceEngine::MemoryBlob::CPtr minput = InferenceEngine::as(inputs[i]); - InferenceEngine::MemoryBlob::Ptr moutput = InferenceEngine::as(outputs[i]); - if (!moutput || !minput) { - return InferenceEngine::StatusCode::PARAMETER_MISMATCH; - } - // locked memory holder should be alive all time while access to its buffer happens - auto minputHolder = minput->rmap(); - auto moutputHolder = moutput->wmap(); - - auto inputData = minputHolder.as(); - auto outputData = moutputHolder.as(); - for (size_t j = 0; j < minput->size(); j++) { - outputData[j] = inputData[j] < 0 ? (-inputData[j] * 2) : inputData[j]; - } + auto inputData = minputHolder.as(); + auto outputData = moutputHolder.as(); + for (size_t j = 0; j < minput->size(); j++) { + outputData[j] = inputData[j] < 0 ? (-inputData[j] * 2) : inputData[j]; } - return InferenceEngine::StatusCode::OK; } + return InferenceEngine::StatusCode::OK; + } - - - private: - const std::shared_ptr node; +private: + const std::shared_ptr node; }; class CustomAbs : public ngraph::op::Op { @@ -100,31 +97,28 @@ public: constexpr ngraph::NodeTypeInfo CustomAbs::type_info; class CustomAbsExtension : public InferenceEngine::IExtension { - public: - CustomAbsExtension() { - } +public: + void GetVersion(const InferenceEngine::Version*& versionInfo) const noexcept override {} - void GetVersion(const InferenceEngine::Version*& versionInfo) const noexcept override {} + void Unload() noexcept override {} - void Unload() noexcept override {} + std::map getOpSets() override { + std::map opsets; + ngraph::OpSet opset; + opset.insert(); + opsets["custom_opset"] = opset; + return opsets; + } - std::map getOpSets() override { - std::map opsets; - ngraph::OpSet opset; - opset.insert(); - opsets["custom_opset"] = opset; - return opsets; - } + std::vector getImplTypes(const std::shared_ptr& node) override { + if (node->description() != CustomAbs::type_info.name) + return {}; + return {"CPU"}; + } - std::vector getImplTypes(const std::shared_ptr& node) override { - if (node->description() != CustomAbs::type_info.name) - return {}; - return {"CPU"}; - } - - InferenceEngine::ILayerImpl::Ptr getImplementation(const std::shared_ptr& node, const std::string& implType) override { - return std::make_shared(node); - } + InferenceEngine::ILayerImpl::Ptr getImplementation(const std::shared_ptr& node, const std::string& implType) override { + return std::make_shared(node); + } }; void infer_model(InferenceEngine::Core& ie, const std::string& model, diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp index 24493069064..c8afd43d056 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp @@ -65,6 +65,9 @@ std::vector disabledTestPatterns() { // Unsupported operation of type: NormalizeL2 name : Doesn't support reduction axes: (2.2) R"(.*BF16NetworkRestore1.*)", R"(.*MobileNet_ssd_with_branching.*)", + + // AUTO plugin and QueryNetwork + R"(.*CoreThreading.*smoke_QueryNetwork.*targetDevice=AUTO_config.*)", }; if (!InferenceEngine::with_cpu_x86_avx512_core()) { diff --git a/inference-engine/tests/functional/plugin/cpu/test_utils/fusing_test_utils.hpp b/inference-engine/tests/functional/plugin/cpu/test_utils/fusing_test_utils.hpp index 2483c74e847..e291919da15 100644 --- a/inference-engine/tests/functional/plugin/cpu/test_utils/fusing_test_utils.hpp +++ b/inference-engine/tests/functional/plugin/cpu/test_utils/fusing_test_utils.hpp @@ -166,7 +166,7 @@ const auto fusingReluAdd = fusingSpecificParams{std::make_shared(s {[](std::shared_ptr inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){ auto shape = inpNode->get_shape(); if (shape.size() == 1) - THROW_IE_EXCEPTION << "If shape.size() == 1 then Granularity can be PerTensor only"; + IE_THROW() << "If shape.size() == 1 then Granularity can be PerTensor only"; ngraph::Shape newShape(shape.size(), 1); newShape[1] = shape[1]; auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector{}, true); @@ -221,7 +221,7 @@ const auto fusingFakeQuantizePerChannel = fusingSpecificParams{std::make_shared< auto localPrc = inpNode->get_element_type(); auto shape = inpNode->get_shape(); if (shape.size() == 1) - THROW_IE_EXCEPTION << "If shape.size() == 1 then Granularity can be PerTensor only"; + IE_THROW() << "If shape.size() == 1 then Granularity can be PerTensor only"; ngraph::Shape newShape(shape.size(), 1); newShape[1] = shape[1]; return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape); diff --git a/inference-engine/tests/functional/plugin/gna/CMakeLists.txt b/inference-engine/tests/functional/plugin/gna/CMakeLists.txt index 83567e31b8f..854e99ee2d5 100644 --- a/inference-engine/tests/functional/plugin/gna/CMakeLists.txt +++ b/inference-engine/tests/functional/plugin/gna/CMakeLists.txt @@ -14,4 +14,12 @@ addIeTargetTest( ADD_CPPLINT LABELS GNA -) \ No newline at end of file +) + +# CVS-55347 +set_source_files_properties( + "${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instances/behavior/add_output.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instances/behavior/memory_states.cpp" + PROPERTIES INCLUDE_DIRECTORIES + $) + diff --git a/inference-engine/tests/functional/plugin/gna/Import_export_tests/import_export_memory_layer.cpp b/inference-engine/tests/functional/plugin/gna/Import_export_tests/import_export_memory_layer.cpp index 8adc666460a..c3f7a0c78ae 100644 --- a/inference-engine/tests/functional/plugin/gna/Import_export_tests/import_export_memory_layer.cpp +++ b/inference-engine/tests/functional/plugin/gna/Import_export_tests/import_export_memory_layer.cpp @@ -65,6 +65,7 @@ public: } auto importedNetwork = core->ImportNetwork(inputStream, targetDevice, configuration); std::vector queryToState; + IE_SUPPRESS_DEPRECATED_START for (const auto &query_state : executableNetwork.QueryState()) { queryToState.push_back(query_state.GetName()); } @@ -72,6 +73,7 @@ public: ASSERT_TRUE(std::find(queryToState.begin(), queryToState.end(), next_memory.GetName()) != queryToState.end()) << "State " << next_memory.GetName() << " expected to be in memory states but it is not!"; } + IE_SUPPRESS_DEPRECATED_END InferenceEngine::InferRequest importInfer = importedNetwork.CreateInferRequest(); importInfer.Infer(); } diff --git a/inference-engine/tests/functional/plugin/gpu/CMakeLists.txt b/inference-engine/tests/functional/plugin/gpu/CMakeLists.txt index 2cc1c9d3bc3..2d9707a3a2f 100644 --- a/inference-engine/tests/functional/plugin/gpu/CMakeLists.txt +++ b/inference-engine/tests/functional/plugin/gpu/CMakeLists.txt @@ -22,6 +22,22 @@ addIeTargetTest( GPU ) +# CVS-55376 +set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/shared_tests_instances/low_precision_transformations/layer_transformation.cpp" + PROPERTIES INCLUDE_DIRECTORIES + $) + +# try to find VA libraries +find_package(PkgConfig QUIET) +if(PkgConfig_FOUND) + pkg_search_module(LIBVA QUIET libva) +endif() + +# TODO: pkg_search_module finds libva not in sysroot +if(ANDROID) + set(LIBVA_FOUND OFF CACHE BOOL "" FORCE) +endif() + if(LIBVA_FOUND) target_compile_definitions(${TARGET_NAME} PRIVATE ENABLE_LIBVA) target_include_directories(${TARGET_NAME} PRIVATE ${LIBVA_INCLUDE_DIRS}) diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/layer_transformation.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/layer_transformation.cpp index 9769e9b9b0d..fd396fd631d 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/layer_transformation.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/layer_transformation.cpp @@ -11,13 +11,12 @@ #include -#include -#include -#include + #include #include #include #include +#include #include #include #include diff --git a/inference-engine/tests/functional/plugin/myriad/ngraph/conversions/dynamic_shape_resolver.cpp b/inference-engine/tests/functional/plugin/myriad/ngraph/conversions/dynamic_shape_resolver.cpp index 9ab50fc501e..25fc4c85cca 100644 --- a/inference-engine/tests/functional/plugin/myriad/ngraph/conversions/dynamic_shape_resolver.cpp +++ b/inference-engine/tests/functional/plugin/myriad/ngraph/conversions/dynamic_shape_resolver.cpp @@ -13,7 +13,6 @@ #include "common_test_utils/test_common.hpp" #include "common_test_utils/common_utils.hpp" -#include #include diff --git a/inference-engine/tests/functional/plugin/shared/CMakeLists.txt b/inference-engine/tests/functional/plugin/shared/CMakeLists.txt index 6bb9f918a2b..c55a06783e2 100644 --- a/inference-engine/tests/functional/plugin/shared/CMakeLists.txt +++ b/inference-engine/tests/functional/plugin/shared/CMakeLists.txt @@ -39,10 +39,15 @@ addIeTarget( ${EXPORT_DEPENDENCIES} ) +# CVS-55376 +set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/src/low_precision_transformations/layer_transformation.cpp" + PROPERTIES INCLUDE_DIRECTORIES + $) + ie_faster_build(${TARGET_NAME} PCH PRIVATE "src/precomp.hpp" ) if (TARGET MKLDNNPlugin) add_dependencies(${TARGET_NAME} MKLDNNPlugin) -endif() \ No newline at end of file +endif() diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/core_threading_tests.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/core_threading_tests.hpp index 1b255e6afbd..c91198bd2e9 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/core_threading_tests.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/core_threading_tests.hpp @@ -13,11 +13,9 @@ #include #include #include -#include #include #include #include -#include #include #include @@ -177,7 +175,7 @@ TEST_P(CoreThreadingTests, smoke_QueryNetwork) { } // -// Parametrized tests with numfer of parallel threads, iterations +// Parameterized tests with number of parallel threads, iterations // using Threads = unsigned int; diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp index c4e0f4ee395..75e1507f112 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include "common_test_utils/common_utils.hpp" @@ -79,54 +78,35 @@ TEST_P(ExecGraphTests, CheckExecGraphInfoBeforeExecution) { originalLayersMap[layer->get_friendly_name()] = 0; } int IteratorForLayersConstant = 0; - if (auto function = execGraph.getFunction()) { - for (const auto & op : function->get_ops()) { - const auto & rtInfo = op->get_rt_info(); - auto getExecValue = [&rtInfo](const std::string & paramName) -> std::string { - auto it = rtInfo.find(paramName); - IE_ASSERT(rtInfo.end() != it); - auto value = std::dynamic_pointer_cast>(it->second); - IE_ASSERT(nullptr != value); + auto function = execGraph.getFunction(); + ASSERT_NE(function, nullptr); - return value->get(); - }; + for (const auto & op : function->get_ops()) { + const auto & rtInfo = op->get_rt_info(); - // Each layer from the execGraphInfo network must have PM data option set - ASSERT_EQ("not_executed", getExecValue(ExecGraphInfoSerialization::PERF_COUNTER)); - // Parse origin layer names (fused/merged layers) from the executable graph - // and compare with layers from the original model - auto origFromExecLayer = getExecValue(ExecGraphInfoSerialization::ORIGINAL_NAMES); - if (origFromExecLayer == "") - IteratorForLayersConstant++; - std::vector origFromExecLayerSep = separateStrToVec(origFromExecLayer, ','); - std::for_each(origFromExecLayerSep.begin(), origFromExecLayerSep.end(), [&](const std::string &layer) { - auto origLayer = originalLayersMap.find(layer); - ASSERT_NE(originalLayersMap.end(), origLayer) << layer; - origLayer->second++; - }); - } - } else { - IE_SUPPRESS_DEPRECATED_START - // Store all the layers from the executable graph information represented as CNNNetwork - const std::vector execGraphLayers = - InferenceEngine::details::CNNNetSortTopologically(execGraph); - for (const auto &execLayer : execGraphLayers) { - // Each layer from the execGraphInfo network must have PM data option set - ASSERT_EQ("not_executed", execLayer->params[ExecGraphInfoSerialization::PERF_COUNTER]); - // Parse origin layer names (fused/merged layers) from the executable graph - // and compare with layers from the original model - auto origFromExecLayer = execLayer->params[ExecGraphInfoSerialization::ORIGINAL_NAMES]; - if (origFromExecLayer == "") - IteratorForLayersConstant++; - std::vector origFromExecLayerSep = separateStrToVec(origFromExecLayer, ','); - std::for_each(origFromExecLayerSep.begin(), origFromExecLayerSep.end(), [&](const std::string &layer) { - auto origLayer = originalLayersMap.find(layer); - ASSERT_NE(originalLayersMap.end(), origLayer) << layer; - origLayer->second++; - }); - } - IE_SUPPRESS_DEPRECATED_END + auto getExecValue = [&rtInfo](const std::string & paramName) -> std::string { + auto it = rtInfo.find(paramName); + IE_ASSERT(rtInfo.end() != it); + auto value = std::dynamic_pointer_cast>(it->second); + IE_ASSERT(nullptr != value); + + return value->get(); + }; + + // Each layer from the execGraphInfo network must have PM data option set + ASSERT_EQ("not_executed", getExecValue(ExecGraphInfoSerialization::PERF_COUNTER)); + // Parse origin layer names (fused/merged layers) from the executable graph + // and compare with layers from the original model + auto origFromExecLayer = getExecValue(ExecGraphInfoSerialization::ORIGINAL_NAMES); + if (origFromExecLayer == "") + IteratorForLayersConstant++; + std::vector origFromExecLayerSep = separateStrToVec(origFromExecLayer, ','); + std::for_each(origFromExecLayerSep.begin(), origFromExecLayerSep.end(), [&](const std::string &layer) { + auto origLayer = originalLayersMap.find(layer); + ASSERT_NE(originalLayersMap.end(), origLayer) << layer; + origLayer->second++; + }); } // All layers from the original IR must be present with in ExecGraphInfo @@ -168,66 +148,40 @@ TEST_P(ExecGraphTests, CheckExecGraphInfoAfterExecution) { int IteratorForLayersConstant = 0; // Store all the layers from the executable graph information represented as CNNNetwork bool has_layer_with_valid_time = false; + auto function = execGraph.getFunction(); + ASSERT_NE(nullptr, function); - if (auto function = execGraph.getFunction()) { - for (const auto & op : function->get_ops()) { - const auto & rtInfo = op->get_rt_info(); + for (const auto & op : function->get_ops()) { + const auto & rtInfo = op->get_rt_info(); - auto getExecValue = [&rtInfo](const std::string & paramName) -> std::string { - auto it = rtInfo.find(paramName); - IE_ASSERT(rtInfo.end() != it); - auto value = std::dynamic_pointer_cast>(it->second); - IE_ASSERT(nullptr != value); + auto getExecValue = [&rtInfo](const std::string & paramName) -> std::string { + auto it = rtInfo.find(paramName); + IE_ASSERT(rtInfo.end() != it); + auto value = std::dynamic_pointer_cast>(it->second); + IE_ASSERT(nullptr != value); - return value->get(); - }; + return value->get(); + }; - // At least one layer in the topology should be executed and have valid perf counter value - try { - float x = static_cast(std::atof( - getExecValue(ExecGraphInfoSerialization::PERF_COUNTER).c_str())); - ASSERT_GE(x, 0.0f); - has_layer_with_valid_time = true; - } catch (std::exception &) {} + // At least one layer in the topology should be executed and have valid perf counter value + try { + float x = static_cast(std::atof( + getExecValue(ExecGraphInfoSerialization::PERF_COUNTER).c_str())); + ASSERT_GE(x, 0.0f); + has_layer_with_valid_time = true; + } catch (std::exception &) {} - // Parse origin layer names (fused/merged layers) from the executable graph - // and compare with layers from the original model - auto origFromExecLayer = getExecValue(ExecGraphInfoSerialization::ORIGINAL_NAMES); - std::vector origFromExecLayerSep = separateStrToVec(origFromExecLayer, ','); - if (origFromExecLayer == "") - IteratorForLayersConstant++; - std::for_each(origFromExecLayerSep.begin(), origFromExecLayerSep.end(), [&](const std::string &layer) { - auto origLayer = originalLayersMap.find(layer); - ASSERT_NE(originalLayersMap.end(), origLayer) << layer; - origLayer->second++; - }); - } - } else { - IE_SUPPRESS_DEPRECATED_START - const std::vector execGraphLayers = - InferenceEngine::details::CNNNetSortTopologically(execGraph); - for (const auto &execLayer : execGraphLayers) { - // At least one layer in the topology should be executed and have valid perf counter value - try { - float x = static_cast(std::atof( - execLayer->params[ExecGraphInfoSerialization::PERF_COUNTER].c_str())); - ASSERT_GE(x, 0.0f); - has_layer_with_valid_time = true; - } catch (std::exception &) {} - - // Parse origin layer names (fused/merged layers) from the executable graph - // and compare with layers from the original model - auto origFromExecLayer = execLayer->params[ExecGraphInfoSerialization::ORIGINAL_NAMES]; - std::vector origFromExecLayerSep = separateStrToVec(origFromExecLayer, ','); - if (origFromExecLayer == "") - IteratorForLayersConstant++; - std::for_each(origFromExecLayerSep.begin(), origFromExecLayerSep.end(), [&](const std::string &layer) { - auto origLayer = originalLayersMap.find(layer); - ASSERT_NE(originalLayersMap.end(), origLayer) << layer; - origLayer->second++; - }); - } - IE_SUPPRESS_DEPRECATED_END + // Parse origin layer names (fused/merged layers) from the executable graph + // and compare with layers from the original model + auto origFromExecLayer = getExecValue(ExecGraphInfoSerialization::ORIGINAL_NAMES); + std::vector origFromExecLayerSep = separateStrToVec(origFromExecLayer, ','); + if (origFromExecLayer == "") + IteratorForLayersConstant++; + std::for_each(origFromExecLayerSep.begin(), origFromExecLayerSep.end(), [&](const std::string &layer) { + auto origLayer = originalLayersMap.find(layer); + ASSERT_NE(originalLayersMap.end(), origLayer) << layer; + origLayer->second++; + }); } ASSERT_TRUE(has_layer_with_valid_time); diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/test_plugin.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/test_plugin.hpp index 2dba0810bc4..81f25912cf9 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/test_plugin.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/test_plugin.hpp @@ -10,10 +10,8 @@ #include #include "ie_extension.h" #include -#include #include #include -#include #include #include #include @@ -47,15 +45,6 @@ TEST_P(BehaviorTests, allocateNullBlob) { ASSERT_NO_THROW(blob.allocate()); } -TEST_P(BehaviorTests, canNotLoadNetworkWithoutWeights) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - InferenceEngine::Core core; - auto model = FuncTestUtils::TestModel::convReluNormPoolFcModelFP32; - ASSERT_THROW(core.ReadNetwork(model.model_xml_str, InferenceEngine::Blob::CPtr()), - InferenceEngine::Exception); -} - TEST_P(BehaviorTests, pluginDoesNotChangeOriginalNetwork) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/caching_tests.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/caching_tests.cpp index d64ce15bd82..0f8f97c6534 100644 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/caching_tests.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/caching_tests.cpp @@ -180,7 +180,7 @@ void LoadNetworkCacheTestBase::Run() { executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice, configuration); GenerateInputs(); Infer(); - } catch (InferenceEngineException &ex) { + } catch (const Exception &ex) { GTEST_COUT << "Can't loadNetwork without cache for " << m_functionName << " with precision " << m_precision.get_type_name() << std::endl; GTEST_COUT << "Exception [" << ex.what() << "]" << std::endl; SKIP(); diff --git a/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/network_serializer.cpp b/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/network_serializer.cpp deleted file mode 100644 index d68ea04d7dc..00000000000 --- a/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/network_serializer.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include - -#include -#include - -using namespace InferenceEngine; - -IE_SUPPRESS_DEPRECATED_START - -std::vector TopologicalSort(const InferenceEngine::CNNNetwork& network) { - std::vector ordered; - std::unordered_set used; - - OutputsDataMap outputs = network.getOutputsInfo(); - InputsDataMap inputs = network.getInputsInfo(); - - auto get_consumers = [](const CNNLayerPtr& node) -> std::vector { - std::vector consumers; - for (const auto & output : node->outData) { - for (const auto &consumer : getInputTo(output)) { - consumers.push_back(consumer.second); - } - } - return consumers; - }; - auto bfs = [&used, &ordered, &get_consumers](const CNNLayerPtr& start_node, bool traverse_via_outputs = false) { - if (!start_node) return; - std::deque q; - q.push_front(start_node); - while (!q.empty()) { - auto node = q.front(); - q.pop_front(); - if (used.insert(node->name).second) { - ordered.push_back(node); - } - - // Traverse via inputs - for (const auto & input : node->insData) { - auto locked_input = input.lock(); - if (!locked_input) { - IE_THROW() << "insData for " << node->name << " is not valid."; - } - if (auto next_node = getCreatorLayer(locked_input).lock()) { - if (!used.count(next_node->name)) { - // Check that all consumers were used - bool all_consumers_used(true); - for (const auto & consumer : get_consumers(next_node)) { - if (!used.count(consumer->name)) all_consumers_used = false; - } - if (all_consumers_used) { - q.push_front(next_node); - } - } - } - } - - // Traverse via outputs - if (traverse_via_outputs) { - for (const auto &consumer : get_consumers(node)) { - if (!used.count(consumer->name)) { - q.push_front(consumer); - } - } - } - } - }; - - // First we run bfs starting from outputs that provides deterministic graph traverse - for (const auto & output : outputs) { - if (!used.count(output.first)) { - bfs(getCreatorLayer(output.second).lock()); - } - } - - // For cases when graph has no outputs we start bfs from inputs to ensure topological sort - for (const auto & input : inputs) { - const auto data_ptr = input.second->getInputData(); - for (const auto & consumer : getInputTo(data_ptr)) - if (!used.count(consumer.first)) { - bfs(consumer.second, true); - } - } - - std::reverse(ordered.begin(), ordered.end()); - return ordered; -} \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/num_inputs_fusing_bin_conv.cpp b/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/num_inputs_fusing_bin_conv.cpp index 4c50b8e960b..4ebf3d78883 100644 --- a/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/num_inputs_fusing_bin_conv.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/num_inputs_fusing_bin_conv.cpp @@ -17,8 +17,6 @@ #include "execution_graph_tests/num_inputs_fusing_bin_conv.hpp" -std::vector TopologicalSort(const InferenceEngine::CNNNetwork& network); - namespace ExecutionGraphTests { std::string ExecGraphInputsFusingBinConv::getTestCaseName(testing::TestParamInfo obj) { @@ -58,60 +56,26 @@ TEST_P(ExecGraphInputsFusingBinConv, CheckNumInputsInBinConvFusingWithConv) { auto execNet = ie->LoadNetwork(cnnNet, targetDevice); InferenceEngine::CNNNetwork execGraphInfo = execNet.GetExecGraphInfo(); + auto function = execGraphInfo.getFunction(); + ASSERT_NE(function, nullptr); - if (auto function = execGraphInfo.getFunction()) { - // try to convert to old representation and check that conversion passed well - std::shared_ptr convertedExecGraph; - ASSERT_NO_THROW(convertedExecGraph = std::make_shared(execGraphInfo)); + for (const auto & op : function->get_ops()) { + const auto & rtInfo = op->get_rt_info(); + auto getExecValue = [&rtInfo](const std::string & paramName) -> std::string { + auto it = rtInfo.find(paramName); + IE_ASSERT(rtInfo.end() != it); + auto value = std::dynamic_pointer_cast>(it->second); + IE_ASSERT(nullptr != value); - for (const auto & op : function->get_ops()) { - const auto & rtInfo = op->get_rt_info(); - auto getExecValue = [&rtInfo](const std::string & paramName) -> std::string { - auto it = rtInfo.find(paramName); - IE_ASSERT(rtInfo.end() != it); - auto value = std::dynamic_pointer_cast>(it->second); - IE_ASSERT(nullptr != value); + return value->get(); + }; - return value->get(); - }; - - auto layerType = getExecValue("layerType"); - if (layerType == "BinaryConvolution") { - auto originalLayersNames = getExecValue("originalLayersNames"); - ASSERT_TRUE(originalLayersNames.find("BinaryConvolution") != std::string::npos); - ASSERT_EQ(op->get_input_size(), 2); - } - - // IR v7 does not have output nodes - if (ngraph::op::is_output(op)) - continue; - - IE_SUPPRESS_DEPRECATED_START - InferenceEngine::CNNLayerPtr cnnLayer; - ASSERT_NO_THROW(cnnLayer = CommonTestUtils::getLayerByName(InferenceEngine::CNNNetwork(convertedExecGraph), op->get_friendly_name())); - ASSERT_EQ(cnnLayer->name, op->get_friendly_name()); - auto variantType = std::dynamic_pointer_cast>( - op->get_rt_info()[ExecGraphInfoSerialization::LAYER_TYPE]);; - ASSERT_EQ(cnnLayer->type, variantType->get()); - - for (const auto & kvp : cnnLayer->params) { - auto variant = std::dynamic_pointer_cast>(op->get_rt_info()[kvp.first]); - ASSERT_EQ(variant->get(), kvp.second); - } - IE_SUPPRESS_DEPRECATED_END + auto layerType = getExecValue("layerType"); + if (layerType == "BinaryConvolution") { + auto originalLayersNames = getExecValue("originalLayersNames"); + ASSERT_TRUE(originalLayersNames.find("BinaryConvolution") != std::string::npos); + ASSERT_EQ(op->get_input_size(), 2); } - } else { - IE_SUPPRESS_DEPRECATED_START - std::vector nodes; - ASSERT_NO_THROW(nodes = TopologicalSort(execGraphInfo)); - for (auto &node : nodes) { - if (node->type == "BinaryConvolution") { - std::string originalLayersNames = node->params["originalLayersNames"]; - ASSERT_TRUE(originalLayersNames.find("BinaryConvolution") != std::string::npos); - ASSERT_EQ(node->insData.size(), 2); - } - } - IE_SUPPRESS_DEPRECATED_END } fnPtr.reset(); diff --git a/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/unique_node_names.cpp b/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/unique_node_names.cpp index ebd8ae366b5..b51ed0a1e6c 100644 --- a/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/unique_node_names.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/execution_graph_tests/unique_node_names.cpp @@ -22,8 +22,6 @@ #include "execution_graph_tests/unique_node_names.hpp" -std::vector TopologicalSort(const InferenceEngine::CNNNetwork& network); - namespace ExecutionGraphTests { std::string ExecGraphUniqueNodeNames::getTestCaseName(testing::TestParamInfo obj) { @@ -46,11 +44,8 @@ void ExecGraphUniqueNodeNames::SetUp() { std::tie(netPrecision, inputShape, targetDevice) = this->GetParam(); auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); - auto split = ngraph::builder::makeSplit(params[0], ngPrc, 2, 1); - auto concat = std::make_shared(split->outputs(), 1); ngraph::ResultVector results{std::make_shared(concat)}; @@ -74,33 +69,22 @@ TEST_P(ExecGraphUniqueNodeNames, CheckUniqueNodeNames) { int expectedReorders = 2; std::unordered_set names; - if (auto function = execGraphInfo.getFunction()) { - for (const auto & op : function->get_ops()) { - ASSERT_TRUE(names.find(op->get_friendly_name()) == names.end()) << - "Node with name " << op->get_friendly_name() << "already exists"; - names.insert(op->get_friendly_name()); + auto function = execGraphInfo.getFunction(); + ASSERT_NE(function, nullptr); - const auto & rtInfo = op->get_rt_info(); - auto it = rtInfo.find(ExecGraphInfoSerialization::LAYER_TYPE); - ASSERT_NE(rtInfo.end(), it); - auto opType = std::dynamic_pointer_cast>(it->second); - ASSERT_NE(nullptr, opType); + for (const auto & op : function->get_ops()) { + ASSERT_TRUE(names.find(op->get_friendly_name()) == names.end()) << + "Node with name " << op->get_friendly_name() << "already exists"; + names.insert(op->get_friendly_name()); - if (opType->get() == "Reorder") { - numReorders++; - } - } - } else { - auto nodes = TopologicalSort(execGraphInfo); - for (auto &node : nodes) { - IE_SUPPRESS_DEPRECATED_START - ASSERT_TRUE(names.find(node->name) == names.end()) << - "Node with name " << node->name << "already exists"; - names.insert(node->name); - if (node->type == "Reorder") { - numReorders++; - } - IE_SUPPRESS_DEPRECATED_END + const auto & rtInfo = op->get_rt_info(); + auto it = rtInfo.find(ExecGraphInfoSerialization::LAYER_TYPE); + ASSERT_NE(rtInfo.end(), it); + auto opType = std::dynamic_pointer_cast>(it->second); + ASSERT_NE(nullptr, opType); + + if (opType->get() == "Reorder") { + numReorders++; } } diff --git a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/depth_to_space_transformation.cpp b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/depth_to_space_transformation.cpp index 7c4fb839ffa..f3169ba9c60 100644 --- a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/depth_to_space_transformation.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/depth_to_space_transformation.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/layer_transformation.cpp b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/layer_transformation.cpp index 1d7e14753d3..ff01c926baa 100644 --- a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/layer_transformation.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/layer_transformation.cpp @@ -43,6 +43,7 @@ namespace LayerTestsUtils { + ngraph::pass::low_precision::LowPrecisionTransformations LayerTransformation::getLowPrecisionTransformationsNGraph( const ngraph::pass::low_precision::LayerTransformation::Params& params) const { return ngraph::pass::low_precision::LowPrecisionTransformer::getAllTransformations(params). diff --git a/inference-engine/tests/functional/plugin/shared/src/ngraph_conversion_tests/conv_bias_fusion.cpp b/inference-engine/tests/functional/plugin/shared/src/ngraph_conversion_tests/conv_bias_fusion.cpp index 0df6eefa9cd..b168ae1a8f3 100644 --- a/inference-engine/tests/functional/plugin/shared/src/ngraph_conversion_tests/conv_bias_fusion.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/ngraph_conversion_tests/conv_bias_fusion.cpp @@ -43,24 +43,19 @@ TEST_P(ConvBiasFusion, ConvBiasFusion) { InferenceEngine::Core ie; InferenceEngine::ExecutableNetwork exeNetwork = ie.LoadNetwork(network, device); auto net = exeNetwork.GetExecGraphInfo(); + auto function = net.getFunction(); + ASSERT_NE(nullptr, function); - if (auto function = net.getFunction()) { - for (const auto & op : function->get_ops()) { - if (op->get_friendly_name() == getOutputName()) { - auto rtInfo = op->get_rt_info(); - auto it = rtInfo.find("originalLayersNames"); - ASSERT_NE(rtInfo.end(), it); - auto variant = std::dynamic_pointer_cast>(it->second); - ASSERT_NE(nullptr, variant); - ASSERT_EQ(variant->get(), "add,conv"); - break; - } + for (const auto & op : function->get_ops()) { + if (op->get_friendly_name() == getOutputName()) { + auto rtInfo = op->get_rt_info(); + auto it = rtInfo.find("originalLayersNames"); + ASSERT_NE(rtInfo.end(), it); + auto variant = std::dynamic_pointer_cast>(it->second); + ASSERT_NE(nullptr, variant); + ASSERT_EQ(variant->get(), "add,conv"); + break; } - } else { - IE_SUPPRESS_DEPRECATED_START - auto add_layer = CommonTestUtils::getLayerByName(net, getOutputName()); - ASSERT_EQ(add_layer->params["originalLayersNames"], "add,conv"); - IE_SUPPRESS_DEPRECATED_END } } diff --git a/inference-engine/tests/functional/shared_test_classes/CMakeLists.txt b/inference-engine/tests/functional/shared_test_classes/CMakeLists.txt index 1e231440d17..ed6d49e0ca2 100644 --- a/inference-engine/tests/functional/shared_test_classes/CMakeLists.txt +++ b/inference-engine/tests/functional/shared_test_classes/CMakeLists.txt @@ -28,7 +28,12 @@ addIeTarget( ${EXPORT_DEPENDENCIES} ) +# CVS-55373 +set_source_files_properties( + "${CMAKE_CURRENT_SOURCE_DIR}/src/subgraph/softsign.cpp" + PROPERTIES INCLUDE_DIRECTORIES + $) + ie_faster_build(${TARGET_NAME} PCH PRIVATE "src/precomp.hpp" ) - diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/low_precision_transformations/layer_transformation.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/low_precision_transformations/layer_transformation.hpp index f1d2fde5d3d..f5cef5abc3e 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/low_precision_transformations/layer_transformation.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/low_precision_transformations/layer_transformation.hpp @@ -8,8 +8,6 @@ #include #include -#include - #include "shared_test_classes/base/layer_test_utils.hpp" #include diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/eltwise.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/eltwise.hpp index 76439bc2d4b..b17b8891922 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/eltwise.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/eltwise.hpp @@ -11,7 +11,6 @@ #include "common_test_utils/common_utils.hpp" #include "common_test_utils/test_common.hpp" #include "common_test_utils/test_constants.hpp" -#include "common_test_utils/common_layers_params.hpp" #include "ie_core.hpp" namespace LayerTestsDefinitions { diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/reduce_ops.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/reduce_ops.hpp index ad8b12deb85..98029b6ebef 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/reduce_ops.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/reduce_ops.hpp @@ -11,7 +11,6 @@ #include "shared_test_classes/base/layer_test_utils.hpp" #include "ngraph_functions/builders.hpp" -#include "common_test_utils/common_layers_params.hpp" namespace LayerTestsDefinitions { diff --git a/inference-engine/tests/functional/shared_test_classes/src/base/low_precision_transformations/layer_transformation.cpp b/inference-engine/tests/functional/shared_test_classes/src/base/low_precision_transformations/layer_transformation.cpp index 72c4c0cd1f5..3a6dd4dc4ea 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/base/low_precision_transformations/layer_transformation.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/base/low_precision_transformations/layer_transformation.cpp @@ -13,8 +13,6 @@ #include "ngraph_functions/pass/convert_prc.hpp" -#include - using namespace InferenceEngine; using namespace ngraph; diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp index f43cca3ca6d..b7c135eb0de 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp @@ -99,6 +99,7 @@ namespace LayerTestsDefinitions { } void GRUSequenceTest::GenerateInputs() { + inputs.clear(); for (const auto &input : executableNetwork.GetInputsInfo()) { const auto &info = input.second; auto blob = GenerateInput(*info); diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/prior_box_clustered.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/prior_box_clustered.cpp index ce85bf79bd4..e13c754d5de 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/prior_box_clustered.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/prior_box_clustered.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "legacy/ngraph_ops/prior_box_clustered_ie.hpp" #include "shared_test_classes/single_layer/prior_box_clustered.hpp" namespace LayerTestsDefinitions { diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/split_concat_memory.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/split_concat_memory.cpp index 828cc25b1a8..bfaf2e877d9 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/split_concat_memory.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/split_concat_memory.cpp @@ -4,7 +4,6 @@ #include "ngraph/opsets/opset5.hpp" #include "shared_test_classes/subgraph/split_concat_memory.hpp" -#include "common_test_utils/xml_net_builder/ir_net.hpp" namespace SubgraphTestsDefinitions { diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/CMakeLists.txt b/inference-engine/tests/ie_test_utils/common_test_utils/CMakeLists.txt index 9d7a0286054..b4c18477cd2 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/CMakeLists.txt +++ b/inference-engine/tests/ie_test_utils/common_test_utils/CMakeLists.txt @@ -75,8 +75,16 @@ function(add_common_utils ADD_TARGET_NAME) PUBLIC ${PUGI} ${NGRAPH_LIBRARIES} + ${EXPORT_DEPENDENCIES} ) + # USE_STATIC_IE is passed + if(ARGN) + target_link_libraries(${ADD_TARGET_NAME} PRIVATE inference_engine_s) + else() + target_link_libraries(${ADD_TARGET_NAME} PRIVATE inference_engine_legacy) + endif() + ie_faster_build(${ADD_TARGET_NAME} UNITY PCH PRIVATE "precomp.hpp" @@ -102,18 +110,13 @@ function(add_common_utils ADD_TARGET_NAME) PUBLIC ${IE_TESTS_ROOT}/ie_test_utils $ - $ $ PRIVATE + $ $ ) target_compile_definitions(${ADD_TARGET_NAME} PUBLIC ${ARGN}) - - target_link_libraries(${ADD_TARGET_NAME} - PUBLIC - ${EXPORT_DEPENDENCIES} - ) endfunction() add_common_utils(${TARGET_NAME}) diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/common_layers_params.cpp b/inference-engine/tests/ie_test_utils/common_test_utils/common_layers_params.cpp index 0ccdbc182a0..081a8d389ff 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/common_layers_params.cpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/common_layers_params.cpp @@ -209,18 +209,4 @@ void get_common_dims(const InferenceEngine::Blob &blob, } } -std::ostream& operator<<(std::ostream & os, OpType type) { - switch (type) { - case OpType::SCALAR: - os << "SCALAR"; - break; - case OpType::VECTOR: - os << "VECTOR"; - break; - default: - IE_THROW() << "NOT_SUPPORTED_OP_TYPE"; - } - return os; -} - } // namespace CommonTestUtils diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/common_layers_params.hpp b/inference-engine/tests/ie_test_utils/common_test_utils/common_layers_params.hpp index b1d5ec5595e..a1e8bf06288 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/common_layers_params.hpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/common_layers_params.hpp @@ -97,10 +97,5 @@ void get_common_dims(const InferenceEngine::Blob &blob, int32_t &dimz, int32_t &dimn); -enum class OpType { - SCALAR, - VECTOR -}; -std::ostream& operator<<(std::ostream & os, OpType type); } // namespace CommonTestUtils diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.cpp b/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.cpp new file mode 100644 index 00000000000..738191890cf --- /dev/null +++ b/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "common_test_utils/common_utils.hpp" +#include + +namespace CommonTestUtils { + +IE_SUPPRESS_DEPRECATED_START + +std::shared_ptr +getLayerByName(const InferenceEngine::CNNNetwork & network, const std::string & layerName) { + InferenceEngine::details::CNNNetworkIterator i(network), end; + while (i != end) { + auto layer = *i; + if (layer->name == layerName) + return layer; + ++i; + } + IE_THROW(NotFound) << "Layer " << layerName << " not found in network"; +} + +IE_SUPPRESS_DEPRECATED_END + +std::ostream& operator<<(std::ostream & os, OpType type) { + switch (type) { + case OpType::SCALAR: + os << "SCALAR"; + break; + case OpType::VECTOR: + os << "VECTOR"; + break; + default: + IE_THROW() << "NOT_SUPPORTED_OP_TYPE"; + } + return os; +} + +} // namespace CommonTestUtils diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.hpp b/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.hpp index 391ada9bf77..dc6aaf2e051 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.hpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.hpp @@ -11,11 +11,29 @@ #include #include #include +#include +#include #include -#include + +namespace InferenceEngine { +class CNNLayer; +} namespace CommonTestUtils { + +enum class OpType { + SCALAR, + VECTOR +}; + +std::ostream& operator<<(std::ostream & os, OpType type); + +IE_SUPPRESS_DEPRECATED_START +std::shared_ptr +getLayerByName(const InferenceEngine::CNNNetwork & network, const std::string & layerName); +IE_SUPPRESS_DEPRECATED_END + template inline std::string vec2str(const std::vector &vec) { if (!vec.empty()) { @@ -49,19 +67,6 @@ inline std::string set2str(const std::set &set) { return std::string("()"); } -inline InferenceEngine::CNNLayerPtr getLayerByName(const InferenceEngine::CNNNetwork & network, - const std::string & layerName) { - IE_SUPPRESS_DEPRECATED_START - InferenceEngine::details::CNNNetworkIterator i(network), end; - while (i != end) { - auto layer = *i; - if (layer->name == layerName) - return layer; - ++i; - } - IE_THROW(NotFound) << "Layer " << layerName << " not found in network"; -} - template std::vector> combineParams( const std::map>& keyValueSets) { diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/CMakeLists.txt b/inference-engine/tests/ie_test_utils/functional_test_utils/CMakeLists.txt index 6ed92869536..7ddc4ed9d07 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/CMakeLists.txt +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/CMakeLists.txt @@ -26,6 +26,9 @@ addIeTarget( inference_engine_transformations inference_engine_lp_transformations inference_engine + PRIVATE + # use this dependency as private in order to minimize + # its usage in 3rd party applications inference_engine_legacy INCLUDES PUBLIC diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/src/layer_test_utils/summary.cpp b/inference-engine/tests/ie_test_utils/functional_test_utils/src/layer_test_utils/summary.cpp index 522f882fb25..6d6a5243cba 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/src/layer_test_utils/summary.cpp +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/src/layer_test_utils/summary.cpp @@ -7,6 +7,9 @@ using namespace LayerTestsUtils; +#ifdef _WIN32 +# define getpid _getpid +#endif Summary *Summary::p_instance = nullptr; bool Summary::extendReport = false; diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/CMakeLists.txt b/inference-engine/tests/ie_test_utils/unit_test_utils/CMakeLists.txt index 50836ed2fb9..7c1d89eabf5 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/CMakeLists.txt +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/CMakeLists.txt @@ -18,6 +18,9 @@ addIeTarget( ADD_CPPLINT DEVELOPER_PACKAGE inference_engine_tests + INCLUDES + PRIVATE + $ EXPORT_DEPENDENCIES ${EXPORT_DEPENDENCIES} ) diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/empty.cpp b/inference-engine/tests/ie_test_utils/unit_test_utils/empty.cpp deleted file mode 100644 index 538e6b03942..00000000000 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/empty.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "unit_test_utils/mocks/mock_allocator.hpp" -#include "unit_test_utils/mocks/mock_icnn_network.hpp" -#include "unit_test_utils/mocks/mock_ie_ivariable_state.hpp" -#include "unit_test_utils/mocks/mock_iexecutable_network.hpp" -#include "unit_test_utils/mocks/mock_iinfer_request.hpp" -#include "unit_test_utils/mocks/mock_not_empty_icnn_network.hpp" - -#include "unit_test_utils/mocks/cpp_interfaces/mock_task_executor.hpp" - -#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_async_infer_request_default.hpp" -#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_executable_network_internal.hpp" -#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_executable_thread_safe_default.hpp" -#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_inference_plugin_internal.hpp" - -#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp" -#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iinfer_request_internal.hpp" -#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_ivariable_state_internal.hpp" -#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp" diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mock.cpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mock.cpp new file mode 100644 index 00000000000..d437fa536af --- /dev/null +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mock.cpp @@ -0,0 +1,65 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "unit_test_utils/mocks/mock_allocator.hpp" +#include "unit_test_utils/mocks/mock_icnn_network.hpp" +#include "unit_test_utils/mocks/mock_ie_ivariable_state.hpp" +#include "unit_test_utils/mocks/mock_iexecutable_network.hpp" +#include "unit_test_utils/mocks/mock_iinfer_request.hpp" +#include "unit_test_utils/mocks/mock_not_empty_icnn_network.hpp" + +#include "unit_test_utils/mocks/cpp_interfaces/mock_task_executor.hpp" + +#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_async_infer_request_default.hpp" +#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_executable_network_internal.hpp" +#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_executable_thread_safe_default.hpp" +#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_inference_plugin_internal.hpp" + +#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp" +#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iinfer_request_internal.hpp" +#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_ivariable_state_internal.hpp" +#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp" + +#include + +using namespace InferenceEngine; + +void MockNotEmptyICNNNetwork::getOutputsInfo(OutputsDataMap& out) const noexcept { + IE_SUPPRESS_DEPRECATED_START + auto data = std::make_shared(MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME, Precision::UNSPECIFIED); + getInputTo(data)[""] = std::make_shared(LayerParams{ + MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME, + "FullyConnected", + Precision::FP32 }); + out[MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME] = data; + IE_SUPPRESS_DEPRECATED_END +} + +void MockNotEmptyICNNNetwork::getInputsInfo(InputsDataMap &inputs) const noexcept { + IE_SUPPRESS_DEPRECATED_START + auto inputInfo = std::make_shared(); + + auto inData = std::make_shared(MockNotEmptyICNNNetwork::INPUT_BLOB_NAME, Precision::UNSPECIFIED); + auto inputLayer = std::make_shared(LayerParams{ + MockNotEmptyICNNNetwork::INPUT_BLOB_NAME, + "Input", + Precision::FP32 }); + getInputTo(inData)[MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME] = inputLayer; + inData->setDims(MockNotEmptyICNNNetwork::INPUT_DIMENTIONS); + inData->setLayout(Layout::NCHW); + inputInfo->setInputData(inData); + + auto outData = std::make_shared(MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME, Precision::UNSPECIFIED); + outData->setDims(MockNotEmptyICNNNetwork::OUTPUT_DIMENTIONS); + outData->setLayout(Layout::NCHW); + getInputTo(outData)[""] = std::make_shared(LayerParams{ + MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME, + "FullyConnected", + Precision::FP32 }); + + inputLayer->outData.push_back(outData); + + inputs[MockNotEmptyICNNNetwork::INPUT_BLOB_NAME] = inputInfo; + IE_SUPPRESS_DEPRECATED_END +} diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_icnn_network.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_icnn_network.hpp index 164eba642ad..618122505a4 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_icnn_network.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_icnn_network.hpp @@ -14,10 +14,13 @@ #include #include "ie_icnn_network.hpp" -#include IE_SUPPRESS_DEPRECATED_START +namespace InferenceEngine { +class CNNLayer; +} // namespace InferenceEngine + /** * @class MockICNNNetwork * @brief Main interface to describe the NN topology @@ -33,7 +36,7 @@ class MockICNNNetwork final : public InferenceEngine::ICNNNetwork { MOCK_QUALIFIED_METHOD0(getName, const noexcept, const std::string&()); MOCK_QUALIFIED_METHOD3(addOutput, noexcept, InferenceEngine::StatusCode(const std::string &, size_t, InferenceEngine::ResponseDesc*)); MOCK_QUALIFIED_METHOD3(getLayerByName, const noexcept, InferenceEngine::StatusCode(const char* , - InferenceEngine::CNNLayerPtr&, + std::shared_ptr&, InferenceEngine::ResponseDesc*)); MOCK_QUALIFIED_METHOD2(setBatchSize, noexcept, InferenceEngine::StatusCode(const size_t size, InferenceEngine::ResponseDesc*)); MOCK_QUALIFIED_METHOD0(getBatchSize, const noexcept, size_t()); diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_not_empty_icnn_network.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_not_empty_icnn_network.hpp index 5be19d7ae5b..b51065d7fd7 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_not_empty_icnn_network.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_not_empty_icnn_network.hpp @@ -10,7 +10,6 @@ #include #include -#include #include "ie_icnn_network.hpp" namespace InferenceEngine { @@ -25,43 +24,8 @@ public: const std::string& getName() const noexcept override { return name; } - void getOutputsInfo(OutputsDataMap& out) const noexcept override { - IE_SUPPRESS_DEPRECATED_START - auto data = std::make_shared(MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME, Precision::UNSPECIFIED); - getInputTo(data)[""] = std::make_shared(LayerParams{ - MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME, - "FullyConnected", - Precision::FP32 }); - out[MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME] = data; - IE_SUPPRESS_DEPRECATED_END - }; - void getInputsInfo(InputsDataMap &inputs) const noexcept override { - IE_SUPPRESS_DEPRECATED_START - auto inputInfo = std::make_shared(); - - auto inData = std::make_shared(MockNotEmptyICNNNetwork::INPUT_BLOB_NAME, Precision::UNSPECIFIED); - auto inputLayer = std::make_shared(LayerParams{ - MockNotEmptyICNNNetwork::INPUT_BLOB_NAME, - "Input", - Precision::FP32 }); - getInputTo(inData)[MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME] = inputLayer; - inData->setDims(MockNotEmptyICNNNetwork::INPUT_DIMENTIONS); - inData->setLayout(Layout::NCHW); - inputInfo->setInputData(inData); - - auto outData = std::make_shared(MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME, Precision::UNSPECIFIED); - outData->setDims(MockNotEmptyICNNNetwork::OUTPUT_DIMENTIONS); - outData->setLayout(Layout::NCHW); - getInputTo(outData)[""] = std::make_shared(LayerParams{ - MockNotEmptyICNNNetwork::OUTPUT_BLOB_NAME, - "FullyConnected", - Precision::FP32 }); - - inputLayer->outData.push_back(outData); - - inputs[MockNotEmptyICNNNetwork::INPUT_BLOB_NAME] = inputInfo; - IE_SUPPRESS_DEPRECATED_END - }; + void getOutputsInfo(OutputsDataMap& out) const noexcept override; + void getInputsInfo(InputsDataMap &inputs) const noexcept override; std::shared_ptr getFunction() noexcept override { return nullptr; } diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/reshape_fully_connected_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/reshape_fully_connected_function.cpp index 72424d4cbee..d06f1d05496 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/reshape_fully_connected_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/reshape_fully_connected_function.cpp @@ -11,7 +11,6 @@ #include #include -#include #include "ngraph_functions/subgraph_builders.hpp" #include "lpt_ngraph_functions/common/builders.hpp" #include "low_precision/network_helper.hpp" diff --git a/inference-engine/tests_deprecated/functional/CMakeLists.txt b/inference-engine/tests_deprecated/functional/CMakeLists.txt index d6bf3a0d281..e5da58a7236 100644 --- a/inference-engine/tests_deprecated/functional/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/CMakeLists.txt @@ -10,14 +10,6 @@ if (ENABLE_MYRIAD) add_subdirectory(vpu) endif() -if (ENABLE_CLDNN) - add_subdirectory(cldnn) -endif() - if (ENABLE_GNA) add_subdirectory(gna) endif() - -if (ENABLE_MKL_DNN) - add_subdirectory(mkldnn) -endif() diff --git a/inference-engine/tests_deprecated/functional/cldnn/CMakeLists.txt b/inference-engine/tests_deprecated/functional/cldnn/CMakeLists.txt deleted file mode 100644 index 6c834d0723e..00000000000 --- a/inference-engine/tests_deprecated/functional/cldnn/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# - -add_executable(ClDnnFunctionalTests dummy.cpp) - -target_link_libraries(ClDnnFunctionalTests PRIVATE gtest_main) diff --git a/inference-engine/tests_deprecated/functional/cldnn/dummy.cpp b/inference-engine/tests_deprecated/functional/cldnn/dummy.cpp deleted file mode 100644 index 936eaeb8151..00000000000 --- a/inference-engine/tests_deprecated/functional/cldnn/dummy.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - diff --git a/inference-engine/tests_deprecated/functional/mkldnn/CMakeLists.txt b/inference-engine/tests_deprecated/functional/mkldnn/CMakeLists.txt deleted file mode 100644 index 9ef991ffee3..00000000000 --- a/inference-engine/tests_deprecated/functional/mkldnn/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# - -add_executable(MklDnnFunctionalTests dummy.cpp) - -target_link_libraries(MklDnnFunctionalTests PRIVATE gtest_main) diff --git a/inference-engine/tests_deprecated/functional/mkldnn/dummy.cpp b/inference-engine/tests_deprecated/functional/mkldnn/dummy.cpp deleted file mode 100644 index ace1c25a6d1..00000000000 --- a/inference-engine/tests_deprecated/functional/mkldnn/dummy.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// diff --git a/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/single_layer_tests.hpp b/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/single_layer_tests.hpp index 6cc9b0abc6c..f76f4f498c7 100644 --- a/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/single_layer_tests.hpp +++ b/inference-engine/tests_deprecated/functional/shared_tests/common_single_layer_tests/single_layer_tests.hpp @@ -10,6 +10,7 @@ #include #include #include +#include "single_layer_common.hpp" #include "conv_ref.hpp" #include "deconv_ref.hpp" From 150b9478e167c597d9a402772b99e2f3d785f282 Mon Sep 17 00:00:00 2001 From: Alexander Zhogov Date: Fri, 14 May 2021 19:27:18 +0300 Subject: [PATCH 76/99] Azure CI: Enable IB for CPU func tests (#5639) --- .ci/azure/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/azure/windows.yml b/.ci/azure/windows.yml index d029cae6fd0..0ae20539c9b 100644 --- a/.ci/azure/windows.yml +++ b/.ci/azure/windows.yml @@ -163,7 +163,7 @@ jobs: - script: | set PATH=$(TEST_ENV_PATH) rem $(BIN_DIR)\cpuFuncTests.exe --gtest_filter=*smoke* --gtest_output=xml:TEST-cpuFuncTests.xml - $(BIN_DIR)\cpuFuncTests.exe --gtest_filter=*smoke*:-*CompareWithRefs/base_size=16_pre_nms_topn=100_post_nms_topn=100_nms_thresh=0.7_feat_stride=1_min_size=1_ratio* --gtest_output=xml:TEST-cpuFuncTests-IB.xml + "$(IB_TESTCONSOLE)" $(BIN_DIR)\cpuFuncTests.exe --gtest_filter=*smoke*:-*CompareWithRefs/base_size=16_pre_nms_topn=100_post_nms_topn=100_nms_thresh=0.7_feat_stride=1_min_size=1_ratio* --gtest_output=xml:TEST-cpuFuncTests-IB.xml /testlevel=24 displayName: 'CPU FuncTests - IB' continueOnError: false From c67c2f469108c939c0722b7bc3b3ea8df14e1f32 Mon Sep 17 00:00:00 2001 From: Andrei Molotkov Date: Fri, 14 May 2021 19:35:08 +0300 Subject: [PATCH 77/99] [IE CLDNN] Improving graph initialization step (#5602) --- .../graph_optimizer/graph_initializations.cpp | 730 +++++++++--------- .../graph_optimizer/handle_input_padding.cpp | 66 +- .../clDNN/src/graph_optimizer/mark_nodes.cpp | 12 +- .../src/graph_optimizer/trim_to_outputs.cpp | 26 +- .../clDNN/src/include/lstm_dynamic_inst.h | 1 + .../clDNN/src/include/pass_manager.h | 11 +- .../clDNN/src/include/program_impl.h | 2 +- .../thirdparty/clDNN/src/program.cpp | 15 +- 8 files changed, 407 insertions(+), 456 deletions(-) diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/graph_initializations.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/graph_initializations.cpp index c4284fc3944..dcd198568d6 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/graph_initializations.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/graph_initializations.cpp @@ -38,420 +38,375 @@ std::string get_id_string(size_t i) { return ss.str(); } -// ToDo: rewrite methods in this class the same style (maybe: handle_() ), -// is it possible to avoid iterating over all nodes several times? -// do we have any repeated code here, can we make it more readable? -void graph_initializations::replace_nodes(program_impl& p) { - auto itr = p.nodes_map.begin(); - while (itr != p.nodes_map.end()) { - auto node_itr = itr++; - auto& node = (*node_itr).second; +void graph_initializations::handle_split_node(program_impl& p, split_node& node) { + if (!node.get_users().empty()) { + throw std::logic_error("Split layer cannot be used directly! Please use split output \"" + node.id() + + ":\"!"); + } + // get_output size and validate split primitive inputs + layout output_layout = node.get_output_layout(); + tensor output_layout_size = output_layout.size; - if (node->is_type()) { - // check if split is not used by any primitive, as it will be optimized - if (node->get_users().size() != 0) - throw std::logic_error("Split layer cannot be used directly! Please use split output \"" + node->id() + - ":\"!"); + auto split_prim = node.typed_desc(); + std::size_t split_num = split_prim->output_offsets.size(); - // get_output size and validate split primitive inputs - auto output_layout = node->get_output_layout(); - auto output_layout_size = output_layout.size; + std::vector transformed_ids; - auto split_prim = node->as().typed_desc(); - primitive_id input_id = split_prim->input[0]; - auto split_num = split_prim->output_offsets.size(); + // create crop for each split output provided + for (std::size_t i = 0; i < split_num; i++) { + primitive_id output_id = node.id() + ":" + split_prim->output_ids[i]; - std::vector transformed_ids; - - // create crop for each split ouptut provided - for (decltype(split_num) i = 0; i < split_num; i++) { - primitive_id output_id = node->id() + ":" + split_prim->output_ids[i]; - transformed_ids.push_back(output_id); - - auto output_node_itr = p.nodes_map.find(output_id); - if (output_node_itr == p.nodes_map.end()) continue; - - auto node_ptr = output_node_itr->second; - - // calculate crop reference input size - tensor reference_input_size; - - // For all the split offsets before the last split offset, the size can be calculated - // size_of_offset[n] = offset[n + 1] - offset[n]; - if (i != (split_num - 1)) { - reference_input_size += split_prim->output_offsets[i + 1] - split_prim->output_offsets[i]; - } else { // For the last split i.e. size[split_num - 1] = split_input.size - offsets[n]; - reference_input_size += output_layout_size - split_prim->output_offsets[i]; - } - - // For all the other dimensions, copy from the split_input - for (int dimension = 0; dimension < tensor_dim_max; dimension++) { - reference_input_size.raw[dimension] = (reference_input_size.raw[dimension] == 0) - ? output_layout_size.raw[dimension] - : reference_input_size.raw[dimension]; - } - - // update crop primitive - node_ptr->set_output_padding(output_layout.data_padding); - auto crop_prim = node_ptr->as().typed_desc(); - crop_prim->reference_input = reference_input_size; - } - - // remove input->split connection and remove original split node - p.remove_connection(node->get_dependency(0), *node); - - p.add_optimized_primitive_info(node->id(), transformed_ids); - p.optimized_out.push_back(node->id()); - p.nodes_map.erase(node->id()); + auto output_node_itr = p.nodes_map.find(output_id); + if (output_node_itr == p.nodes_map.end()) { continue; } + + transformed_ids.push_back(std::move(output_id)); + + auto node_ptr = output_node_itr->second; + + // calculate crop reference input size + tensor reference_input_size; + + // For all the split offsets before the last split offset, the size can be calculated + // size_of_offset[n] = offset[n + 1] - offset[n]; + if (i != (split_num - 1)) { + reference_input_size += split_prim->output_offsets[i + 1] - split_prim->output_offsets[i]; + } else { // For the last split i.e. size[split_num - 1] = split_input.size - offsets[n]; + reference_input_size += output_layout_size - split_prim->output_offsets[i]; + } + + // For all the other dimensions, copy from the split_input + for (int32_t dimension = 0; dimension < tensor_dim_max; dimension++) { + if (reference_input_size.raw[dimension] == 0) { + reference_input_size.raw[dimension] = output_layout_size.raw[dimension]; + } + } + + // update crop primitive + node_ptr->set_output_padding(output_layout.data_padding); + auto crop_prim = node_ptr->as().typed_desc(); + crop_prim->reference_input = reference_input_size; } + + // remove input->split connection and remove original split node + p.remove_connection(node.input(), node); + + p.add_optimized_primitive_info(node.id(), transformed_ids); + p.optimized_out.push_back(node.id()); + p.nodes_map.erase(node.id()); } -void graph_initializations::handle_lstm(program_impl& p) { - bool has_lstm_children; - auto itr = p.nodes_map.begin(); // note we need to use iterators since currently processed element can be removed - while (itr != p.nodes_map.end()) { - auto node_itr = itr++; - auto& node = (*node_itr).second; - has_lstm_children = false; - // replace lstm node with lstm_gemm and lstm_elt nodes - if (node->is_type()) { - bool initial_hidden_term = node->as().initial_hidden_term(); - bool initial_cell_term = node->as().initial_cell_term(); - bool bias_term = node->as().bias_term(); - auto lstm_prim = node->as().typed_desc(); - primitive_id weights_id = lstm_prim->weights; - primitive_id recurrent_id = lstm_prim->recurrent; - primitive_id bias_id = bias_term ? lstm_prim->bias : ""; - primitive_id initial_hidden_id = initial_hidden_term ? lstm_prim->initial_hidden : ""; - primitive_id initial_cell_id = initial_cell_term ? lstm_prim->initial_cell : ""; +void graph_initializations::handle_lstm_node(program_impl& p, lstm_node& node) { + // lstm_node& lstm_node = node->as(); + bool initial_hidden_term = node.initial_hidden_term(); + bool initial_cell_term = node.initial_cell_term(); + bool bias_term = node.bias_term(); + auto lstm_prim = node.typed_desc(); + primitive_id weights_id = lstm_prim->weights; + primitive_id recurrent_id = lstm_prim->recurrent; + primitive_id bias_id = bias_term ? lstm_prim->bias : ""; + primitive_id initial_hidden_id = initial_hidden_term ? lstm_prim->initial_hidden : ""; + primitive_id initial_cell_id = initial_cell_term ? lstm_prim->initial_cell : ""; - // removing connection with weights to get proper dependency order for next operations - p.remove_connection(*p.nodes_map.at(weights_id), *node); - p.remove_connection(*p.nodes_map.at(recurrent_id), *node); + // removing connection with weights to get proper dependency order for next operations + p.remove_connection(p.get_node(weights_id), node); + p.remove_connection(p.get_node(recurrent_id), node); + if (bias_term) + p.remove_connection(p.get_node(bias_id), node); + if (initial_hidden_term) + p.remove_connection(p.get_node(initial_hidden_id), node); + if (initial_cell_term) + p.remove_connection(p.get_node(initial_cell_id), node); + + // calculating sizes + program_node& input = node.input(); + layout input_layout = input.get_output_layout(); + tensor input_size = input_layout.size; + tensor recurrent_size = p.get_node(recurrent_id).get_output_layout().size; + + // hidden tensor size = [batch, seq, hidden_size, direction] + // the output of the element wise operation is cropped and used in the next time step + // sequence_len = 1 and direction = 1. The backward pass is separated from the forward pass + auto hidden_size = tensor(input_size.batch[0], 1, recurrent_size.spatial[0], 1); + + size_t directions = recurrent_size.feature[0]; + size_t num_input_dependencies = node.get_dependencies().size(); + size_t sequence_len = node.sequence_len(); + + // Calculate the input sequence length for the lstm node + // Case 1: If the input comes in as a concatenated input i.e. the + // input is not divided into sequence elements + if (sequence_len == 1 && num_input_dependencies == 1) { + // Get the sequence length from the input to LSTM + sequence_len = input_size.feature[0]; + + // If the input's feature/sequence length field is > 1, i.e. If + // the sequence elements are concatenated into one single input + // then it has to be split into individual sequence elements + if (sequence_len > 1) { + for (size_t sequence_element = 0; sequence_element < sequence_len; sequence_element++) { + primitive_id crop_id = input.id() + ":crop:" + get_id_string(sequence_element); + tensor crop_tensor{input_size.batch[0], 1, input_size.spatial[0], input_size.spatial[1]}; + tensor offset_tensor{0, static_cast(sequence_element), 0, 0}; + auto input_crop = std::make_shared(crop_id, input.id(), crop_tensor, offset_tensor); + auto& input_crop_node = p.get_or_create(input_crop); + + // Add the crop nodes as user for input + p.add_connection(input, input_crop_node); + + // Connect crop with lstm + p.add_connection(input_crop_node, node); + } + + // We have the sequence elements (cropped inputs) as input to LSTM. + // The original input is no longer a dependency to LSTM. + // Remove the input node as a dependency to LSTM + p.remove_connection(input, node); + + // Update the total no. of input dependecies + num_input_dependencies = node.get_dependencies().size(); + } + // if the sequence has a single element but it has multiple inputs then + // the parent of this lstm is an lstm node. If this is a bidirectional lstm + // then the sequence length is the number of dependencies divided by 2. + } else if (sequence_len == 1 && num_input_dependencies > 1) { + sequence_len = (directions == 1) ? num_input_dependencies : num_input_dependencies / 2; + } + + // check if this lstm node has an lstm child + bool has_lstm_children = false; + for (auto& user : node.get_users()) { + if (user->is_type()) { + has_lstm_children = true; + } + } + + bool emit_last_cell = lstm_prim->output_selection == lstm_output_selection::hidden_cell || + lstm_prim->output_selection == lstm_output_selection::sequence_cell; + bool emit_sequence = lstm_prim->output_selection == lstm_output_selection::sequence_cell || + lstm_prim->output_selection == lstm_output_selection::sequence; + + std::vector cell_list(directions * sequence_len); + std::vector hidden_list(directions * sequence_len); + std::map> output_map; + size_t input_directions = input_size.spatial[1]; + + // lstm expanding + for (size_t dir = 0; dir < directions; ++dir) { + auto hidden_id = initial_hidden_id; + auto cell_id = initial_cell_id; + for (size_t i = 0; i < sequence_len; ++i) { + size_t idx = i + dir * sequence_len; + primitive_id lstm_gemm_id = node.id() + ":lstm_gemm" + get_id_string(idx); + primitive_id lstm_elt_id = node.id() + ":lstm_elt" + get_id_string(idx); + primitive_id crop_id = node.id() + ":crop" + get_id_string(idx); + + size_t input_idx = i; + // for bidirectional lstms, if first LSTM layer then reverse input + // for subsequent stacked layers the input is strided on the dir dimension + if (num_input_dependencies > sequence_len) { // stacked layer + input_idx = dir * sequence_len + i; + } else if ((input_directions < 2) && dir > 0) { // first layer + input_idx = sequence_len - i - 1; + } + + // primitive_id lstm_gemm_input_id = node->get_dependency(input_idx).get_primitive()->id; + // the line below requires an attention: get_org_primitive_id() might not be an actual id of a node + // (see rename method) ToDO: ensure that get_org_primitive_id() is suitable here + primitive_id lstm_gemm_input_id = node.get_dependency(input_idx).get_org_primitive_id(); + + auto lstm_gemm_node = std::make_shared(lstm_gemm_id, + lstm_gemm_input_id, + weights_id, + recurrent_id, + bias_id, + hidden_id, + (uint32_t)dir); + auto& n1 = p.get_or_create(lstm_gemm_node); + + auto lstm_elt_node = std::make_shared(lstm_elt_id, + lstm_gemm_id, + cell_id, + lstm_prim->clip, + lstm_prim->input_forget, + lstm_prim->activations, + lstm_prim->activation_params, + lstm_prim->offset_order, + (uint32_t)dir); + auto& n2 = p.get_or_create(lstm_elt_node); + // adding lstm_elt as user + p.add_connection(n1, n2); + // adding dependecy to lstm_gemm node + // input + p.add_connection(node.get_dependency(input_idx), n1); + // adding weights and initial values to lstm_gemm + p.add_connection(p.get_node(weights_id), n1); + p.add_connection(p.get_node(recurrent_id), n1); if (bias_term) - p.remove_connection(*p.nodes_map.at(bias_id), *node); - if (initial_hidden_term) - p.remove_connection(*p.nodes_map.at(initial_hidden_id), *node); - if (initial_cell_term) - p.remove_connection(*p.nodes_map.at(initial_cell_id), *node); + p.add_connection(p.get_node(bias_id), n1); - // calculating sizes - auto input_size = node->get_dependency(0).get_output_layout().size; - auto recurrent_size = p.nodes_map.at(recurrent_id)->get_output_layout().size; - - // hidden tensor size = [batch, seq, hidden_size, direction] - // the output of the element wise operation is cropped and used in the next time step - // sequence_len = 1 and direction = 1. The backward pass is separated from the forward pass - auto hidden_size = tensor(input_size.batch[0], 1, recurrent_size.spatial[0], 1); - - size_t directions = recurrent_size.feature[0]; - size_t input_directions = input_size.spatial[1]; - size_t num_input_dependencies = node->get_dependencies().size(); - size_t input_vector_size = node->as().sequence_len(); - size_t sequence_len = input_vector_size; - - // Calculate the input sequence length for the lstm node - // Case 1: If the input comes in as a concatenated input i.e. the - // input is not divided into sequence elements - if (input_vector_size == 1 && num_input_dependencies == 1) { - // Either the input actually has 1 sequence element - auto& input = node->get_dependency(0); - auto input_layout = input.get_output_layout(); - tensor input_tensor = input_layout.size; - - // Get the sequence length from the input to LSTM - sequence_len = input_layout.size.feature[0]; - - // If the input's feature/sequence length field is > 1, i.e. If - // the sequence elements are concatenated into one single input - // then it has to be split into individual sequence elements - if (sequence_len > 1) { - for (size_t sequence_element = 0; sequence_element < sequence_len; sequence_element++) { - primitive_id crop_id = input.id() + ":crop:" + get_id_string(sequence_element); - tensor crop_tensor{input_tensor.batch[0], 1, input_tensor.spatial[0], input_tensor.spatial[1]}; - tensor offset_tensor{0, static_cast(sequence_element), 0, 0}; - auto input_crop = std::make_shared(crop_id, input.id(), crop_tensor, offset_tensor); - auto& input_crop_node = p.get_or_create(input_crop); - - // Add the crop nodes as user for input - p.add_connection(node->get_dependency(0), input_crop_node); - - // Connect crop with lstm - p.add_connection(input_crop_node, *node); - } - - // We have the sequence elements (cropped inputs) as input to LSTM. - // The original input is no longer a dependency to LSTM. - // Remove the input node as a dependency to LSTM - p.remove_connection(node->get_dependency(0), *node); - - // Update the total no. of input dependecies - num_input_dependencies = node->get_dependencies().size(); - } - // if the sequence has a single element but it has multiple inputs then - // the parent of this lstm is an lstm node. If this is a bidirectional lstm - // then the sequence length is the number of dependencies divided by 2. - } else if (input_vector_size == 1 && num_input_dependencies > 1) { - sequence_len = (directions == 1) ? num_input_dependencies : num_input_dependencies / 2; + // adding cell and hiddens as dependencies + if (i > 0) { + p.add_connection(*cell_list[(i - 1) * directions + dir], n2); + p.add_connection(*hidden_list[(i - 1) * directions + dir], n1); + } else { // if initial values are present + if (initial_hidden_term) + p.add_connection(p.get_node(hidden_id), n1); + if (initial_cell_term) + p.add_connection(p.get_node(cell_id), n2); } - // check if this lstm node has an lstm child - for (auto& user : node->get_users()) { - if (user->is_type()) { - has_lstm_children = true; + // lstm_hidden + { + hidden_id = crop_id + ":hidden"; + auto crop_hidden = + std::make_shared(hidden_id, lstm_elt_id, hidden_size, tensor{0, 0, 0, 0}); + auto& n3 = p.get_or_create(crop_hidden); + // adding eltwise as dependency to hidden + p.add_connection(n2, n3); + + // if parent is lstm adding hiddens as dependency + if (has_lstm_children) { + for (auto& user : node.get_users()) { + p.add_connection(n3, *user); + } + } + hidden_list[i * directions + dir] = &n3; + if (i == sequence_len - 1 || emit_sequence) { + output_map[i * directions + dir] = {hidden_id, &n3}; } } - bool emit_last_cell = lstm_prim->output_selection == lstm_output_selection::hidden_cell || - lstm_prim->output_selection == lstm_output_selection::sequence_cell; - bool emit_sequence = lstm_prim->output_selection == lstm_output_selection::sequence_cell || - lstm_prim->output_selection == lstm_output_selection::sequence; - - std::vector cell_list(directions * sequence_len); - std::vector hidden_list(directions * sequence_len); - std::map> output_map; - auto dependencies = node->get_dependencies(); - - // lstm expanding - for (size_t dir = 0; dir < directions; ++dir) { - auto hidden_id = initial_hidden_id; - auto cell_id = initial_cell_id; - for (size_t i = 0; i < sequence_len; ++i) { - size_t idx = i + dir * sequence_len; - primitive_id lstm_gemm_id = node->id() + ":lstm_gemm" + get_id_string(idx); - primitive_id lstm_elt_id = node->id() + ":lstm_elt" + get_id_string(idx); - primitive_id crop_id = node->id() + ":crop" + get_id_string(idx); - - size_t input_idx = i; - // for bidirectional lstms, if first LSTM layer then reverse input - // for subsequent stacked layers the input is strided on the dir dimension - if (directions > 0) { - if (num_input_dependencies > sequence_len) { // stacked layer - input_idx = dir * sequence_len + i; - } else { - if ((input_directions < 2) && dir > 0) { // first layer - input_idx = sequence_len - i - 1; - } - } - } - - // primitive_id lstm_gemm_input_id = node->get_dependency(input_idx).get_primitive()->id; - // the line below requires an attention: get_org_primitive_id() might not be an actual id of a node - // (see rename method) ToDO: ensure that get_org_primitive_id() is suitable here - primitive_id lstm_gemm_input_id = node->get_dependency(input_idx).get_org_primitive_id(); - - auto lstm_gemm_node = std::make_shared(lstm_gemm_id, - lstm_gemm_input_id, - weights_id, - recurrent_id, - bias_id, - hidden_id, - (uint32_t)dir); - auto& n1 = p.get_or_create(lstm_gemm_node); - - auto lstm_elt_node = std::make_shared(lstm_elt_id, - lstm_gemm_id, - cell_id, - lstm_prim->clip, - lstm_prim->input_forget, - lstm_prim->activations, - lstm_prim->activation_params, - lstm_prim->offset_order, - (uint32_t)dir); - auto& n2 = p.get_or_create(lstm_elt_node); - // adding lstm_elt as user - p.add_connection(n1, n2); - // adding dependecy to lstm_gemm node - // input - p.add_connection(node->get_dependency(input_idx), n1); - // adding weights and initial values to lstm_gemm - p.add_connection(*p.nodes_map.at(weights_id), n1); - p.add_connection(*p.nodes_map.at(recurrent_id), n1); - if (bias_term) - p.add_connection(*p.nodes_map.at(bias_id), n1); - - // adding cell and hiddens as dependencies - if (i > 0) { - p.add_connection(*cell_list[size_t(i - 1) * directions + dir], n2); - p.add_connection(*hidden_list[size_t(i - 1) * directions + dir], n1); - } else { // if initial values are present - if (initial_hidden_term) - p.add_connection(*p.nodes_map.at(hidden_id), n1); - if (initial_cell_term) - p.add_connection(*p.nodes_map.at(cell_id), n2); - } - - // lstm_hidden - { - hidden_id = crop_id + ":hidden"; - auto crop_hidden = - std::make_shared(hidden_id, lstm_elt_id, hidden_size, tensor{0, 0, 0, 0}); - auto& n3 = p.get_or_create(crop_hidden); - // adding eltwise as dependency to hidden - p.add_connection(n2, n3); - - // if parent is lstm adding hiddens as dependency - if (has_lstm_children) { - for (auto& user : node->get_users()) { - p.add_connection(n3, *user); - } - } - hidden_list[i * directions + dir] = &n3; - if (i == sequence_len - 1 || emit_sequence) { - output_map[i * directions + dir] = {hidden_id, &n3}; - } - } - - // lstm_cell - if (i < sequence_len - 1 || emit_last_cell) { - cell_id = crop_id + ":cell"; - auto crop_cell = std::make_shared(cell_id, lstm_elt_id, hidden_size, tensor{0, 1, 0, 0}); - auto& n4 = p.get_or_create(crop_cell); - p.add_connection(n2, n4); - cell_list[i * directions + dir] = &n4; - if (i == sequence_len - 1) { - output_map[sequence_len * directions + dir] = {cell_id, &n4}; - } - } + // lstm_cell + if (i < sequence_len - 1 || emit_last_cell) { + cell_id = crop_id + ":cell"; + auto crop_cell = std::make_shared(cell_id, lstm_elt_id, hidden_size, tensor{0, 1, 0, 0}); + auto& n4 = p.get_or_create(crop_cell); + p.add_connection(n2, n4); + cell_list[i * directions + dir] = &n4; + if (i == sequence_len - 1) { + output_map[sequence_len * directions + dir] = {cell_id, &n4}; } } - // if there is no next lstm, concatenation is created - if (!has_lstm_children) { - std::vector output_ids_offsets; - for (auto& e : output_map) { - output_ids_offsets.push_back(e.second.first); - } - primitive_id original_id = node->id(); - primitive_id concatenation_id = original_id + ":concat"; - auto concatenation_primitive = - std::make_shared(concatenation_id, output_ids_offsets, concatenation::along_f); - auto& concatenation_node = p.get_or_create(concatenation_primitive); - for (auto& e : output_map) { - p.add_connection(*e.second.second, concatenation_node); - } - if (directions == 2) { - // bidirectional support requires concatenations along the direction and sequence axis - // instead we can concatenate along the sequence axis and reshape the tensor to the account - // for the direction - size_t concatenate_len = emit_sequence ? sequence_len : 1; - if (emit_last_cell) - concatenate_len++; - - tensor output_size{input_size.batch[0], - static_cast(concatenate_len), - hidden_size.spatial[0], - (int32_t)directions}; - primitive_id reshape_id = original_id + ":reshape"; - auto reshape_primitive = std::make_shared(reshape_id, concatenation_id, output_size); - auto& reshape_node = p.get_or_create(reshape_primitive); - p.add_connection(concatenation_node, reshape_node); - p.replace_all_usages(*node, reshape_node); - } else { - p.replace_all_usages(*node, concatenation_node); - } - } - // removing expanded node - p.remove_all_connections(*node); - p.nodes_map.erase(node->id()); - continue; } } + // if there is no next lstm, concatenation is created + if (!has_lstm_children) { + std::vector output_ids_offsets; + for (auto& e : output_map) { + output_ids_offsets.push_back(e.second.first); + } + primitive_id concatenation_id = node.id() + ":concat"; + auto concatenation_primitive = + std::make_shared(concatenation_id, output_ids_offsets, concatenation::along_f); + auto& concatenation_node = p.get_or_create(concatenation_primitive); + for (auto& e : output_map) { + p.add_connection(*e.second.second, concatenation_node); + } + if (directions == 2) { + // bidirectional support requires concatenations along the direction and sequence axis + // instead we can concatenate along the sequence axis and reshape the tensor to the account + // for the direction + size_t concatenate_len = emit_sequence ? sequence_len : 1; + if (emit_last_cell) + concatenate_len++; + + tensor output_size{input_size.batch[0], + static_cast(concatenate_len), + hidden_size.spatial[0], + (int32_t)directions}; + auto reshape_primitive = std::make_shared(node.id() + ":reshape", concatenation_id, output_size); + auto& reshape_node = p.get_or_create(reshape_primitive); + p.add_connection(concatenation_node, reshape_node); + p.replace_all_usages(node, reshape_node); + } else { + p.replace_all_usages(node, concatenation_node); + } + } + // removing expanded node + p.remove_all_connections(node); + p.nodes_map.erase(node.id()); } -void graph_initializations::handle_dynamic_lstm(program_impl& p) { - /* - We need to replace lstm_dynamic with lstm_dynamic_input + lstm_dynamic_timeloop. - */ - auto itr = p.nodes_map.begin(); - while (itr != p.nodes_map.end()) { - auto node_itr = itr++; - auto& node = (*node_itr).second; +void graph_initializations::handle_dynamic_lstm_node(program_impl& p, lstm_dynamic_node& node) { + // [0] Prepare helper temp variables. + // auto& lstm_dynamic_node = node->as(); + auto& node_id = node.id(); + auto input_id = node.get_primitive()->input.at(0); + auto dyn_length_id = node.dyn_length_id(); + auto weights_id = node.weights_id(); + auto bias_id = node.bias_id(); + std::string suffix = "__cldnn_"; - if (node->is_type()) { - // [0] Prepare helper temp variables. - auto& lstm_dynamic_node = node->as(); - auto& node_id = lstm_dynamic_node.id(); - auto input_id = node->get_primitive()->input.at(0); - auto dyn_length_id = lstm_dynamic_node.dyn_length_id(); - auto weights_id = lstm_dynamic_node.weights_id(); - auto recurrent_id = lstm_dynamic_node.recurrent_id(); - auto bias_id = lstm_dynamic_node.bias_id(); - auto init_hidden_id = lstm_dynamic_node.initial_hidden_id(); - auto init_cell_id = lstm_dynamic_node.initial_cell_id(); - auto last_hidden_id = lstm_dynamic_node.last_hidden_state_id(); - auto last_cell_id = lstm_dynamic_node.last_cell_state_id(); - auto clip = lstm_dynamic_node.clip(); - auto input_forget = lstm_dynamic_node.input_forget(); - std::string suffix = "__cldnn_"; + // [1] Add lstm_dynamic_input + auto lstm_dynamic_input_primitive = + std::make_shared(node_id + suffix + "input", + input_id, + dyn_length_id, + weights_id, + bias_id, + node.get_primitive()->output_padding); + auto& lstm_dynamic_input_node = p.get_or_create(lstm_dynamic_input_primitive); + p.add_connection(node.input(), lstm_dynamic_input_node); // connect real input to dlstm_input + // connect other deps + p.add_connection(p.get_node(dyn_length_id), lstm_dynamic_input_node); + p.add_connection(p.get_node(weights_id), lstm_dynamic_input_node); + if (!bias_id.empty()) + p.add_connection(p.get_node(bias_id), lstm_dynamic_input_node); + lstm_dynamic_input_node.get_output_layout(); // calc out layout - // [1] Add lstm_dynamic_input - auto lstm_dynamic_input_primitive = - std::make_shared(node_id + suffix + "input", - input_id, - dyn_length_id, - weights_id, - bias_id, - node->get_primitive()->output_padding); - auto& lstm_dynamic_input_node = p.get_or_create(lstm_dynamic_input_primitive); - p.add_connection(node->get_dependency(0), lstm_dynamic_input_node); // connect real input to dlstm_input - // connect other deps - p.add_connection(p.get_node(dyn_length_id), lstm_dynamic_input_node); - p.add_connection(p.get_node(weights_id), lstm_dynamic_input_node); - if (!bias_id.empty()) - p.add_connection(p.get_node(bias_id), lstm_dynamic_input_node); - lstm_dynamic_input_node.get_output_layout(); // calc out layout + auto recurrent_id = node.recurrent_id(); + auto init_hidden_id = node.initial_hidden_id(); + auto init_cell_id = node.initial_cell_id(); + auto last_hidden_id = node.last_hidden_state_id(); + auto last_cell_id = node.last_cell_state_id(); + auto lstm_dynamic_timeloop_primitive = + std::make_shared(node_id + suffix + "timeloop", + lstm_dynamic_input_node.id(), + dyn_length_id, + recurrent_id, + last_hidden_id, + last_cell_id, + init_hidden_id, + init_cell_id, + node.clip(), + node.input_forget(), + lstm_dynamic_input_primitive->output_padding); + auto& lstm_dynamic_timeloop_node = p.get_or_create(lstm_dynamic_timeloop_primitive); + p.add_connection(lstm_dynamic_input_node, lstm_dynamic_timeloop_node); // connect dlstm_input to dlstm_timeloop + // connect other deps + p.add_connection(p.get_node(dyn_length_id), lstm_dynamic_timeloop_node); + p.add_connection(p.get_node(recurrent_id), lstm_dynamic_timeloop_node); - auto lstm_dynamic_timeloop_primitive = - std::make_shared(node_id + suffix + "timeloop", - lstm_dynamic_input_node.id(), - dyn_length_id, - recurrent_id, - last_hidden_id, - last_cell_id, - init_hidden_id, - init_cell_id, - clip, - input_forget, - lstm_dynamic_input_primitive->output_padding); - auto& lstm_dynamic_timeloop_node = p.get_or_create(lstm_dynamic_timeloop_primitive); - p.add_connection(lstm_dynamic_input_node, - lstm_dynamic_timeloop_node); // connect dlstm_input to dlstm_timeloop - // connect other deps - p.add_connection(p.get_node(dyn_length_id), lstm_dynamic_timeloop_node); - p.add_connection(p.get_node(recurrent_id), lstm_dynamic_timeloop_node); + // [hack] reversed dependecies so the prociessing/execution order will be valid (from the user persepctive) + // It means that this optional outputs for sure will be "executed" layer. + // This connection will be reversed (to normal state) later in program.cpp (right after caluticaiton prcoessing order)! + if (!last_hidden_id.empty()) + p.add_connection(lstm_dynamic_timeloop_node, p.get_node(last_hidden_id)); + if (!last_cell_id.empty()) + p.add_connection(lstm_dynamic_timeloop_node, p.get_node(last_cell_id)); + // [hack end] + if (!init_hidden_id.empty()) + p.add_connection(p.get_node(init_hidden_id), lstm_dynamic_timeloop_node); + if (!init_cell_id.empty()) + p.add_connection(p.get_node(init_cell_id), lstm_dynamic_timeloop_node); + lstm_dynamic_timeloop_node.get_output_layout(); // calc out layout - // [hack] reversed dependecies so the prociessing/execution order will be valid (from the user persepctive) - // It means that this optional outputs for sure will be "executed" layer. - // This connection will be reversed (to normal state) later in program.cpp (right after caluticaiton prcoessing order)! - if (!last_hidden_id.empty()) - p.add_connection(lstm_dynamic_timeloop_node, p.get_node(last_hidden_id)); - if (!last_cell_id.empty()) - p.add_connection(lstm_dynamic_timeloop_node, p.get_node(last_cell_id)); - // [hack end] - if (!init_hidden_id.empty()) - p.add_connection(p.get_node(init_hidden_id), lstm_dynamic_timeloop_node); - if (!init_cell_id.empty()) - p.add_connection(p.get_node(init_cell_id), lstm_dynamic_timeloop_node); - lstm_dynamic_timeloop_node.get_output_layout(); // calc out layout + // [2] Finally replace original node with the new ones. + p.replace_all_usages(node, lstm_dynamic_timeloop_node); + p.remove_all_connections(node); + p.remove_if_dangling(node); + p.rename(lstm_dynamic_timeloop_node, node_id); // get original id - // [2] Finally replace original node with the new ones. - p.replace_all_usages(*node, lstm_dynamic_timeloop_node); - p.remove_all_connections(*node); - p.remove_if_dangling(*node); - p.rename(lstm_dynamic_timeloop_node, node_id); // get original id - - // we dont have to set output since it will be done in next graph_opts step - } - } + // we dont have to set output since it will be done in next graph_opts step } void graph_initializations::set_outputs(program_impl& p) { auto outputs_option = p.get_options().get(); if (!outputs_option->outputs.empty()) { for (auto const& output : outputs_option->outputs) { - auto o_node = p.nodes_map.at(output); + auto o_node = p.get_node_ptr(output); o_node->set_output(true); p.outputs.push_back(o_node.get()); } @@ -465,9 +420,18 @@ void graph_initializations::set_outputs(program_impl& p) { } void graph_initializations::run(program_impl& p) { - replace_nodes(p); - handle_lstm(p); - handle_dynamic_lstm(p); + auto itr = p.nodes_map.begin(); + while (itr != p.nodes_map.end()) { + auto node_itr = itr++; + auto& node = node_itr->second; + if (node->is_type()) { + handle_split_node(p, node->as()); + } else if (node->is_type()) { + handle_lstm_node(p, node->as()); + } else if (node->is_type()) { + handle_dynamic_lstm_node(p, node->as()); + } + } set_outputs(p); p.get_processing_order().calc_processing_order(p); } diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/handle_input_padding.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/handle_input_padding.cpp index 76e6b1bc5b1..137ced81fc2 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/handle_input_padding.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/handle_input_padding.cpp @@ -18,71 +18,66 @@ using namespace cldnn; // Asymmetric padding can be done by adding border primitive before them. It's safe way without modyfing optimized // kernels. void handle_input_padding::run(program_impl& p) { - auto processing_order = p.get_processing_order(); - - for (auto& node : processing_order) { - if (node->is_type() && (node->as().get_primitive()->padding_above.spatial[0] != 0 || - node->as().get_primitive()->padding_above.spatial[1] != 0 || - node->as().get_primitive()->padding_below.spatial[0] != 0 || - node->as().get_primitive()->padding_below.spatial[1] != 0)) { - auto conv = node->as().get_primitive(); - auto conv_primitive = const_cast(&(*conv)); + for (auto& node : p.get_processing_order()) { + if (!node->is_type()) { + continue; + } + convolution_node& convolution_node = node->as(); + auto convolution_prim = const_cast(&(*convolution_node.get_primitive())); + if (convolution_prim->padding_above.spatial[0] != 0 || convolution_prim->padding_above.spatial[1] != 0 || + convolution_prim->padding_below.spatial[0] != 0 || convolution_prim->padding_below.spatial[1] != 0) { // Asymmetric padding - if (node->as().get_primitive()->padding_above.spatial[0] != - node->as().get_primitive()->padding_below.spatial[0] || - node->as().get_primitive()->padding_above.spatial[1] != - node->as().get_primitive()->padding_below.spatial[1]) { - primitive_id conv_id = conv_primitive->id; - primitive_id input_id = conv_primitive->input[0]; + if (convolution_prim->padding_above.spatial[0] != convolution_prim->padding_below.spatial[0] || + convolution_prim->padding_above.spatial[1] != convolution_prim->padding_below.spatial[1]) { + const primitive_id& convolution_node_id = convolution_node.id(); + tensor padding_above = convolution_prim->padding_above; + tensor padding_below = convolution_prim->padding_below; - auto padding_above = conv_primitive->padding_above; - auto padding_below = conv_primitive->padding_below; - - CLDNN_ERROR_NOT_EQUAL(node->as().id(), + CLDNN_ERROR_NOT_EQUAL(convolution_node_id, "Padding above feature", padding_above.feature[0], "", 0, "Padding above in feature is not supported"); - CLDNN_ERROR_NOT_EQUAL(node->as().id(), + CLDNN_ERROR_NOT_EQUAL(convolution_node_id, "Padding above batch", padding_above.batch[0], "", 0, "Padding above in batch is not supported"); - CLDNN_ERROR_NOT_EQUAL(node->as().id(), + CLDNN_ERROR_NOT_EQUAL(convolution_node_id, "Padding below feature", padding_below.feature[0], "", 0, "Padding below in feature is not supported"); - CLDNN_ERROR_NOT_EQUAL(node->as().id(), + CLDNN_ERROR_NOT_EQUAL(convolution_node_id, "Padding below batch", padding_below.batch[0], "", 0, "Padding below in batch is not supported"); - CLDNN_ERROR_LESS_THAN(node->as().id(), + CLDNN_ERROR_LESS_THAN(convolution_node_id, "Padding above X", padding_above.spatial[0], "", 0, "Padding above in X cannot be negative"); - CLDNN_ERROR_LESS_THAN(node->as().id(), + CLDNN_ERROR_LESS_THAN(convolution_node_id, "Padding above Y", padding_above.spatial[1], "", 0, "Padding above in Y cannot be negative"); - CLDNN_ERROR_LESS_THAN(node->as().id(), + CLDNN_ERROR_LESS_THAN(convolution_node_id, "Padding below X", padding_below.spatial[0], "", 0, "Padding below in X cannot be negative"); - CLDNN_ERROR_LESS_THAN(node->as().id(), + CLDNN_ERROR_LESS_THAN(convolution_node_id, "Padding below Y", padding_below.spatial[1], "", @@ -90,11 +85,12 @@ void handle_input_padding::run(program_impl& p) { "Padding below in Y cannot be negative"); // set padding_above/padding_below to zeros - border primitive do the job - conv_primitive->padding_above = tensor(0, 0, 0, 0); - conv_primitive->padding_below = tensor(0, 0, 0, 0); + convolution_prim->padding_above = tensor(0, 0, 0, 0); + convolution_prim->padding_below = tensor(0, 0, 0, 0); // create border primitive - primitive_id border_id = input_id + "_border_" + conv_id; + primitive_id input_id = convolution_prim->input[0]; + primitive_id border_id = input_id + "_border_" + convolution_prim->id; auto b_prim = std::make_shared(border_id, input_id, padding_above, @@ -104,18 +100,16 @@ void handle_input_padding::run(program_impl& p) { auto& b_prim_node = p.get_or_create(b_prim); - p.add_intermediate(b_prim_node, *node, 0, true); - - continue; + p.add_intermediate(b_prim_node, convolution_node, 0, true); } else { // Symmetric padding // set input_offset - conv_primitive->input_offset = conv_primitive->padding_above.negate().add(conv_primitive->input_offset); + convolution_prim->input_offset = convolution_prim->padding_above.negate().add(convolution_prim->input_offset); // set padding_above/padding_below to zeros - input_offset do the job - conv_primitive->padding_above = tensor(0, 0, 0, 0); - conv_primitive->padding_below = tensor(0, 0, 0, 0); + convolution_prim->padding_above = tensor(0, 0, 0, 0); + convolution_prim->padding_below = tensor(0, 0, 0, 0); - node->as().recalc_output_layout(true); + convolution_node.recalc_output_layout(true); } } } diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/mark_nodes.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/mark_nodes.cpp index 6b9c0ddcdcc..c7b74650a8a 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/mark_nodes.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/mark_nodes.cpp @@ -10,18 +10,8 @@ using namespace cldnn; void mark_nodes::run(program_impl& p) { - mark_constants(p); - mark_data_flow(p); -} - -void mark_nodes::mark_constants(program_impl& p) { - for (auto& node : p.get_processing_order()) { + for (const auto& node : p.get_processing_order()) { p.mark_if_constant(*node); - } -} - -void mark_nodes::mark_data_flow(program_impl& p) { - for (auto const& node : p.get_processing_order()) { p.mark_if_data_flow(*node); } } diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/trim_to_outputs.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/trim_to_outputs.cpp index d8c9c2e1dd7..a981b93b886 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/trim_to_outputs.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/trim_to_outputs.cpp @@ -11,21 +11,20 @@ #include "max_unpooling_inst.h" #include "pooling_inst.h" #include -#include +#include using namespace cldnn; // This pass optimizes out nodes which have no impact on outputs void trim_to_outputs::run(program_impl& p) { const size_t actual_nodes = p.get_processing_order().size(); - if (!actual_nodes) // degenerated case but can happen - return; - - if (p.get_outputs().size() == actual_nodes) + if (actual_nodes == 0 || actual_nodes == p.get_outputs().size()) { return; + } // do backward bfs starting from all outputs - std::list*> stack = {&(p.get_outputs())}; + std::queue*> queue; + queue.push(&p.get_outputs()); std::vector special_nodes; for (auto& node : p.get_processing_order()) { @@ -36,23 +35,24 @@ void trim_to_outputs::run(program_impl& p) { (node->is_type() && node->as().get_primitive()->mode == pooling_mode::max_with_argmax)) special_nodes.push_back(node); } - stack.push_back(&special_nodes); + queue.push(&special_nodes); - while (!stack.empty()) { - auto nodes_list = stack.front(); - stack.pop_front(); + while (!queue.empty()) { + auto nodes_list = queue.front(); + queue.pop(); for (auto& node : *nodes_list) { if (!node->is_marked()) { node->mark(); - if (!node->get_dependencies().empty()) - stack.push_back(&node->get_dependencies()); + if (!node->get_dependencies().empty()) { + queue.push(&node->get_dependencies()); + } } } } // all not-marked nodes should be removed - std::list to_rem; + std::vector to_rem; for (auto& node : p.get_processing_order()) { if (!node->is_marked()) to_rem.push_back(node); diff --git a/inference-engine/thirdparty/clDNN/src/include/lstm_dynamic_inst.h b/inference-engine/thirdparty/clDNN/src/include/lstm_dynamic_inst.h index 24d1fb95d29..c64530ffae9 100644 --- a/inference-engine/thirdparty/clDNN/src/include/lstm_dynamic_inst.h +++ b/inference-engine/thirdparty/clDNN/src/include/lstm_dynamic_inst.h @@ -17,6 +17,7 @@ struct typed_program_node : public typed_program_node_base prim, program_impl& prog) : parent(prim, prog) {} + program_node& input() const { return get_dependency(0); } float clip() const { return get_primitive()->clip; } bool input_forget() const { return get_primitive()->input_forget; } primitive_id bias_id() const { return get_primitive()->bias; } diff --git a/inference-engine/thirdparty/clDNN/src/include/pass_manager.h b/inference-engine/thirdparty/clDNN/src/include/pass_manager.h index 1e2173e3c73..698554a6d25 100644 --- a/inference-engine/thirdparty/clDNN/src/include/pass_manager.h +++ b/inference-engine/thirdparty/clDNN/src/include/pass_manager.h @@ -6,6 +6,9 @@ #include "program_impl.h" #include "layout_optimizer.h" +#include "split_inst.h" +#include "lstm_inst.h" +#include "lstm_dynamic_inst.h" #include #include #include @@ -102,9 +105,9 @@ public: private: void run(program_impl& p) override; - void replace_nodes(program_impl& p); - void handle_lstm(program_impl& p); - void handle_dynamic_lstm(program_impl& p); + void handle_split_node(program_impl& p, split_node& node); + void handle_lstm_node(program_impl& p, lstm_node& node); + void handle_dynamic_lstm_node(program_impl& p, lstm_dynamic_node& node); void set_outputs(program_impl& p); }; @@ -130,8 +133,6 @@ public: private: void run(program_impl& p) override; - void mark_constants(program_impl& p); - void mark_data_flow(program_impl& p); }; class prepare_buffer_fusing : public base_pass { diff --git a/inference-engine/thirdparty/clDNN/src/include/program_impl.h b/inference-engine/thirdparty/clDNN/src/include/program_impl.h index cafc2a8b44c..4df1b34c7be 100644 --- a/inference-engine/thirdparty/clDNN/src/include/program_impl.h +++ b/inference-engine/thirdparty/clDNN/src/include/program_impl.h @@ -196,7 +196,7 @@ public: void mark_if_data_flow(program_node& node); // Reverses connection - user becomes dependency. - void remove_nodes(std::list& to_remove); + void remove_nodes(std::vector& to_remove); void dump_program(const char* stage, bool with_full_info, std::function const& filter = nullptr) const; diff --git a/inference-engine/thirdparty/clDNN/src/program.cpp b/inference-engine/thirdparty/clDNN/src/program.cpp index 76b109bf75c..870bfd4f968 100644 --- a/inference-engine/thirdparty/clDNN/src/program.cpp +++ b/inference-engine/thirdparty/clDNN/src/program.cpp @@ -486,15 +486,14 @@ void program_impl::post_optimize_graph(bool is_internal) { // mark if the node is constant assuming that all dependencies are marked properly void program_impl::mark_if_constant(program_node& node) { - if (node.get_dependencies().empty()) - return; - if (node.is_type()) + if (node.get_dependencies().empty() || node.is_type()) { return; + } node.constant = true; for (auto& dep : node.get_dependencies()) { - if (!dep->constant) { + if (!dep->is_constant()) { node.constant = false; - break; + return; } } } @@ -976,12 +975,14 @@ void program_impl::fuse_nodes(program_node &fused_node, program_node &peer_node, fused_node.recalc_output_layout(true); } -void program_impl::remove_nodes(std::list& to_remove) { +void program_impl::remove_nodes(std::vector& to_remove) { for (auto const& node : to_remove) { if (node->is_input()) { get_inputs().remove(node); } else { - for (auto& dep : node->dependencies) dep->users.remove(node); + for (auto& dep : node->dependencies) { + dep->users.remove(node); + } } for (auto& user : node->users) { user->dependencies.erase(std::remove(user->dependencies.begin(), user->dependencies.end(), node), From c500f0a783cbb91ccac1f687d6e4b67ef440f000 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 14 May 2021 21:27:12 +0300 Subject: [PATCH 78/99] Removed CPU GEMM cmake stuff (#5642) * Removed CPU GEMM cmake stuff * Fixed code style --- inference-engine/cmake/dependencies.cmake | 56 ------------------- inference-engine/cmake/features.cmake | 17 ------ .../src/mkldnn_plugin/CMakeLists.txt | 33 ++--------- .../emitters/jit_bf16_emitters.hpp | 6 +- .../emitters/jit_eltwise_emitters.hpp | 6 +- .../emitters/jit_mkldnn_emitters.hpp | 2 +- .../mkldnn_plugin/nodes/mkldnn_conv_node.h | 2 +- .../src/mkldnn_plugin/nodes/mkldnn_mvn_node.h | 4 +- .../mkldnn_plugin/nodes/mkldnn_roll_node.h | 2 +- .../src/mkldnn_plugin/utils/ngraph_utils.hpp | 2 +- 10 files changed, 18 insertions(+), 112 deletions(-) diff --git a/inference-engine/cmake/dependencies.cmake b/inference-engine/cmake/dependencies.cmake index a9261df7964..85adfd45089 100644 --- a/inference-engine/cmake/dependencies.cmake +++ b/inference-engine/cmake/dependencies.cmake @@ -38,62 +38,6 @@ if (ENABLE_MYRIAD) include(cmake/vpu_dependencies.cmake) endif() -## enable cblas_gemm from OpenBLAS package -if (ENABLE_MKL_DNN AND GEMM STREQUAL "OPENBLAS") - if(AARCH64) - if(DEFINED ENV{THIRDPARTY_SERVER_PATH}) - set(IE_PATH_TO_DEPS "$ENV{THIRDPARTY_SERVER_PATH}") - elseif(DEFINED THIRDPARTY_SERVER_PATH) - set(IE_PATH_TO_DEPS "${THIRDPARTY_SERVER_PATH}") - else() - message(WARNING "OpenBLAS is not found!") - endif() - - if(DEFINED IE_PATH_TO_DEPS) - reset_deps_cache(OpenBLAS_DIR) - - RESOLVE_DEPENDENCY(OpenBLAS - ARCHIVE_LIN "keembay/openblas_0.3.7_yocto_kmb.tar.xz" - TARGET_PATH "${TEMP}/openblas_0.3.7_yocto_kmb" - ENVIRONMENT "OpenBLAS_DIR" - SHA256 "c75aac901d5297d6d60a4b1f941f0335d8fd7f52e0dff8c445f644e2e45e6fba") - - update_deps_cache(OpenBLAS_DIR "${OpenBLAS}/lib/cmake/openblas" "Path to OpenBLAS package folder") - - find_package(OpenBLAS QUIET) - - if(OpenBLAS_FOUND) - set(BLAS_FOUND TRUE) - set(BLAS_INCLUDE_DIRS ${OpenBLAS_INCLUDE_DIRS}) - set(BLAS_LIBRARIES ${OpenBLAS_LIBRARIES}) - endif() - - unset(IE_PATH_TO_DEPS) - endif() - endif() - - if(NOT BLAS_LIBRARIES OR NOT BLAS_INCLUDE_DIRS) - find_package(BLAS REQUIRED) - - if(BLAS_FOUND) - find_path(BLAS_INCLUDE_DIRS cblas.h) - else() - message(ERROR "OpenBLAS not found: install OpenBLAS or set -DBLAS_INCLUDE_DIRS= and -DBLAS_LIBRARIES=") - endif() - endif() - - debug_message(STATUS "openblas=" ${BLAS_LIBRARIES}) -endif () - -## MKL-ML package -if (GEMM STREQUAL "MKL") - if(NOT MKLROOT) - message(FATAL_ERROR "MKLROOT not found: install MKL and set -DMKLROOT=") - endif() - set(MKL ${MKLROOT}) - debug_message(STATUS "mkl_ml=" ${MKLROOT}) -endif () - ## Intel OMP package if (THREADING STREQUAL "OMP") reset_deps_cache(OMP) diff --git a/inference-engine/cmake/features.cmake b/inference-engine/cmake/features.cmake index db7a0028f60..6c42fe16a1e 100644 --- a/inference-engine/cmake/features.cmake +++ b/inference-engine/cmake/features.cmake @@ -8,23 +8,6 @@ ie_dependent_option (ENABLE_GNA "GNA support for inference engine" ON "NOT APPLE ie_dependent_option (ENABLE_CLDNN_TESTS "Enable clDNN unit tests" OFF "ENABLE_CLDNN" OFF) -# "MKL-DNN library might use MKL-ML or OpenBLAS for gemm tasks: MKL|OPENBLAS|JIT" -if (ENABLE_MKL_DNN) - if(AARCH64) - set(GEMM_DEFAULT "OPENBLAS") - else() - set(GEMM_DEFAULT "JIT") - endif() - set(GEMM "${GEMM_DEFAULT}" CACHE STRING "GEMM implementation") - set_property(CACHE GEMM PROPERTY STRINGS "MKL" "OPENBLAS" "JIT") - list (APPEND IE_OPTIONS GEMM) - if (NOT GEMM STREQUAL "MKL" AND - NOT GEMM STREQUAL "OPENBLAS" AND - NOT GEMM STREQUAL "JIT") - message(FATAL_ERROR "GEMM should be set to MKL, OPENBLAS or JIT. Default option is ${GEMM_DEFAULT}") - endif() -endif() - # "MKL-DNN library based on OMP or TBB or Sequential implementation: TBB|OMP|SEQ" if(X86 OR ARM OR (MSVC AND (ARM OR AARCH64)) ) set(THREADING_DEFAULT "SEQ") diff --git a/inference-engine/src/mkldnn_plugin/CMakeLists.txt b/inference-engine/src/mkldnn_plugin/CMakeLists.txt index 388a600a697..fe57b29ddf6 100644 --- a/inference-engine/src/mkldnn_plugin/CMakeLists.txt +++ b/inference-engine/src/mkldnn_plugin/CMakeLists.txt @@ -16,25 +16,16 @@ if (ENABLE_CPU_DEBUG_CAPS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCPU_DEBUG_CAPS") endif() -file(GLOB_RECURSE SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) -file(GLOB HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) - -addVersionDefines(mkldnn_plugin.cpp CI_BUILD_NUMBER MKL_VERSION) +addVersionDefines(mkldnn_plugin.cpp CI_BUILD_NUMBER) include_directories( $ ${CMAKE_CURRENT_SOURCE_DIR}/mkldnn - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_BINARY_DIR}/include -) - -if (GEMM STREQUAL "MKL") - log_rpath_from_dir(MKL "${MKL}/lib") -endif() + ${CMAKE_CURRENT_SOURCE_DIR}) # create plugin @@ -99,17 +90,3 @@ set_target_properties(${TARGET_NAME}_obj PROPERTIES EXCLUDE_FROM_ALL ON) set_target_properties(${TARGET_NAME} ${TARGET_NAME}_obj PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) - -# install - -if(GEMM STREQUAL "MKL") - install(DIRECTORY "${MKL}/include" - DESTINATION ${IE_CPACK_IE_DIR}/external/mkltiny_lnx - COMPONENT cpu) - install(FILES "${MKLLIB}" - DESTINATION ${IE_CPACK_IE_DIR}/external/mkltiny_lnx/lib - COMPONENT cpu) - install(FILES "${MKL}/version.info" - DESTINATION ${IE_CPACK_IE_DIR}/external/mkltiny_lnx - COMPONENT cpu) -endif() diff --git a/inference-engine/src/mkldnn_plugin/emitters/jit_bf16_emitters.hpp b/inference-engine/src/mkldnn_plugin/emitters/jit_bf16_emitters.hpp index 75ebf5b41d3..454a6c335af 100644 --- a/inference-engine/src/mkldnn_plugin/emitters/jit_bf16_emitters.hpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_bf16_emitters.hpp @@ -13,9 +13,9 @@ public: jit_emu_vcvtneps2bf16(mkldnn::impl::cpu::x64::jit_generator* host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::BF16) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); - }; + } - size_t get_inputs_num() const override { return 1; }; + size_t get_inputs_num() const override { return 1; } private: void emit_impl(const std::vector& in_vec_idxs, const std::vector& out_vec_idxs, @@ -71,4 +71,4 @@ private: size_t aux_vecs_count() const override { return 2; } }; -} // namespace MKLDNNPlugin { \ No newline at end of file +} // namespace MKLDNNPlugin \ No newline at end of file diff --git a/inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.hpp b/inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.hpp index 7bd63c59c02..50ddb57bad6 100644 --- a/inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.hpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.hpp @@ -190,9 +190,11 @@ private: class jit_squared_difference_emitter : public jit_emitter { public: - jit_squared_difference_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, + jit_squared_difference_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, + const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - jit_squared_difference_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + jit_squared_difference_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, + const std::shared_ptr& n, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); size_t get_inputs_num() const override; diff --git a/inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.hpp b/inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.hpp index e045279307a..7c40d5fd713 100644 --- a/inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.hpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.hpp @@ -23,6 +23,7 @@ public: void emit_impl(const std::vector &in_idxs, const std::vector &out_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, const emitter_context *emit_context = nullptr) const override {}; + protected: jit_mkldnn_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); @@ -34,7 +35,6 @@ protected: float alpha {0.f}; float beta {0.f}; -protected: std::shared_ptr> eltwise_injector_sse42; std::shared_ptr> eltwise_injector_avx2; std::shared_ptr> eltwise_injector_avx512_common; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h index a0a400dc008..d2ebc152987 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_conv_node.h @@ -59,7 +59,7 @@ protected: private: void addZeroPoints(mkldnn::primitive_attr& attr) const; - void setPostOps(mkldnn::primitive_attr &attr, bool initWeights) const ; + void setPostOps(mkldnn::primitive_attr &attr, bool initWeights) const; void filterSupportedDescriptors(); bool isPossibleToSkipInitConfig(MKLDNNDescriptor &desc) const; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h index d988c1d103c..9ce7e784e40 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.h @@ -86,11 +86,11 @@ public: inline bool getAcrossChannels() const { return acrossChannels_; - }; + } inline bool getNormalizeVariance() const { return normalizeVariance_; - }; + } bool canFuse(const MKLDNNNodePtr& node) const override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roll_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roll_node.h index c8118caa153..da597d4d981 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roll_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roll_node.h @@ -29,7 +29,7 @@ private: void rollImpl(); std::vector shape; - const static std::vector supportedPrecisionSizes; + static const std::vector supportedPrecisionSizes; std::string layerErrorPrefix; size_t numOfDims; diff --git a/inference-engine/src/mkldnn_plugin/utils/ngraph_utils.hpp b/inference-engine/src/mkldnn_plugin/utils/ngraph_utils.hpp index d4ea7a2088b..c6b54febc5a 100644 --- a/inference-engine/src/mkldnn_plugin/utils/ngraph_utils.hpp +++ b/inference-engine/src/mkldnn_plugin/utils/ngraph_utils.hpp @@ -18,7 +18,7 @@ inline std::string getRTInfoValue(const std::map &node) { const auto &rtInfo = node->get_rt_info(); From 717499cf2f7b6b9c0619249603ac17aa8a3a0916 Mon Sep 17 00:00:00 2001 From: Evgeny Lazarev Date: Fri, 14 May 2021 21:56:03 +0300 Subject: [PATCH 79/99] Common telemetry (#5032) * Moved telemetry to repo root directory from MO * New telemetry package in the "openvino" sub-directory * Removed telemetry from the MO BOM * Updated MO BOM and added stub file for telemetry * Fixed license header * Fixed license headers and cleaned up the telemetry setup.py * Fixed import * Added temporary dependency for openvino-telemetry * Added ignore for pylint issues * Fixed import statements * Updated imports in the telemetry library * Removed telemetry library. Added link to another private repo * Removed redundant start_session event for the MO * Changed approach to import the telemetry library * Minor code refactoring * Updated MO telemetry events sending messages * Refactor sending events for the IE runtime check * Disable forcing warnings for deprecated methods * Removed changes from the requirements.txt to install telemetry library to avoid merge conflicts * Update copyright in the model-optimizer/mo/utils/telemetry_stub.py Co-authored-by: Gleb Kazantaev Co-authored-by: Gleb Kazantaev --- model-optimizer/automation/package_BOM.txt | 11 +-- .../mo/back/offline_transformations.py | 6 +- model-optimizer/mo/main.py | 15 +-- model-optimizer/mo/utils/check_ie_bindings.py | 33 ++++--- model-optimizer/mo/utils/ie_version.py | 2 +- model-optimizer/mo/utils/telemetry_stub.py | 29 ++++++ model-optimizer/mo/utils/utils.py | 2 - model-optimizer/telemetry/__init__.py | 3 - model-optimizer/telemetry/backend/__init__.py | 4 - model-optimizer/telemetry/backend/backend.py | 81 ----------------- .../telemetry/backend/backend_ga.py | 87 ------------------ model-optimizer/telemetry/telemetry.py | 91 ------------------- model-optimizer/telemetry/utils/__init__.py | 3 - model-optimizer/telemetry/utils/guid.py | 64 ------------- model-optimizer/telemetry/utils/isip.py | 70 -------------- model-optimizer/telemetry/utils/message.py | 18 ---- model-optimizer/telemetry/utils/sender.py | 59 ------------ model-optimizer/unit_tests/mo/bom_test.py | 2 +- 18 files changed, 64 insertions(+), 516 deletions(-) create mode 100644 model-optimizer/mo/utils/telemetry_stub.py delete mode 100644 model-optimizer/telemetry/__init__.py delete mode 100644 model-optimizer/telemetry/backend/__init__.py delete mode 100644 model-optimizer/telemetry/backend/backend.py delete mode 100644 model-optimizer/telemetry/backend/backend_ga.py delete mode 100644 model-optimizer/telemetry/telemetry.py delete mode 100644 model-optimizer/telemetry/utils/__init__.py delete mode 100644 model-optimizer/telemetry/utils/guid.py delete mode 100644 model-optimizer/telemetry/utils/isip.py delete mode 100644 model-optimizer/telemetry/utils/message.py delete mode 100644 model-optimizer/telemetry/utils/sender.py diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index b6f7236c35f..c18d0f8dd93 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -1072,6 +1072,7 @@ mo/utils/shape.py mo/utils/simple_proto_parser.py mo/utils/str_to.py mo/utils/summarize_graph.py +mo/utils/telemetry_stub.py mo/utils/tensorboard_util.py mo/utils/unsupported_ops.py mo/utils/utils.py @@ -1089,13 +1090,3 @@ requirements_mxnet.txt requirements_onnx.txt requirements_tf.txt requirements_tf2.txt -telemetry/__init__.py -telemetry/backend/__init__.py -telemetry/backend/backend.py -telemetry/backend/backend_ga.py -telemetry/telemetry.py -telemetry/utils/__init__.py -telemetry/utils/guid.py -telemetry/utils/isip.py -telemetry/utils/message.py -telemetry/utils/sender.py diff --git a/model-optimizer/mo/back/offline_transformations.py b/model-optimizer/mo/back/offline_transformations.py index e9069547484..ee8905356ac 100644 --- a/model-optimizer/mo/back/offline_transformations.py +++ b/model-optimizer/mo/back/offline_transformations.py @@ -9,7 +9,7 @@ from mo.utils.cli_parser import parse_transform def get_available_transformations(): try: - from openvino.offline_transformations import ApplyLowLatencyTransformation # pylint: disable=import-error + from openvino.offline_transformations import ApplyLowLatencyTransformation # pylint: disable=import-error,no-name-in-module return { 'LowLatency': ApplyLowLatencyTransformation, } @@ -22,8 +22,8 @@ def apply_offline_transformations(input_model: str, framework: str, transforms: # to produce correct mapping extract_names = framework in ['tf', 'mxnet', 'kaldi'] - from openvino.inference_engine import read_network # pylint: disable=import-error - from openvino.offline_transformations import ApplyMOCTransformations, GenerateMappingFile # pylint: disable=import-error + from openvino.inference_engine import read_network # pylint: disable=import-error,no-name-in-module + from openvino.offline_transformations import ApplyMOCTransformations, GenerateMappingFile # pylint: disable=import-error,no-name-in-module net = read_network(input_model + "_tmp.xml", input_model + "_tmp.bin") diff --git a/model-optimizer/mo/main.py b/model-optimizer/mo/main.py index 2a289f2d3b8..83cf4d22db2 100644 --- a/model-optimizer/mo/main.py +++ b/model-optimizer/mo/main.py @@ -6,15 +6,19 @@ import datetime import logging as log import os import platform -import sys import subprocess +import sys import traceback from collections import OrderedDict from copy import deepcopy import numpy as np -import telemetry.telemetry as tm +try: + import openvino_telemetry as tm +except ImportError: + import mo.utils.telemetry_stub as tm + from extensions.back.SpecialNodesFinalization import RemoveConstOps, CreateConstNodesReplacement, NormalizeTI from mo.back.ie_ir_ver_2.emitter import append_ir_info from mo.graph.graph import Graph @@ -107,7 +111,6 @@ def prepare_ir(argv: argparse.Namespace): log.debug(str(argv)) log.debug("Model Optimizer started") t = tm.Telemetry() - t.start_session() model_name = "" if argv.model_name: @@ -373,7 +376,7 @@ def driver(argv: argparse.Namespace): def main(cli_parser: argparse.ArgumentParser, framework: str): telemetry = tm.Telemetry(app_name='Model Optimizer', app_version=get_simplified_mo_version()) - telemetry.start_session() + telemetry.start_session('mo') telemetry.send_event('mo', 'version', get_simplified_mo_version()) try: # Initialize logger with 'ERROR' as default level to be able to form nice messages @@ -391,7 +394,7 @@ def main(cli_parser: argparse.ArgumentParser, framework: str): if ov_update_message: print(ov_update_message) telemetry.send_event('mo', 'conversion_result', 'success') - telemetry.end_session() + telemetry.end_session('mo') telemetry.force_shutdown(1.0) return ret_code except (FileNotFoundError, NotADirectoryError) as e: @@ -418,7 +421,7 @@ def main(cli_parser: argparse.ArgumentParser, framework: str): log.error("-------------------------------------------------") telemetry.send_event('mo', 'conversion_result', 'fail') - telemetry.end_session() + telemetry.end_session('mo') telemetry.force_shutdown(1.0) return 1 diff --git a/model-optimizer/mo/utils/check_ie_bindings.py b/model-optimizer/mo/utils/check_ie_bindings.py index 12c9e039e37..fe03294bad1 100644 --- a/model-optimizer/mo/utils/check_ie_bindings.py +++ b/model-optimizer/mo/utils/check_ie_bindings.py @@ -3,12 +3,10 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import os -import re -import sys import argparse +import os import platform - +import sys try: import mo @@ -19,15 +17,22 @@ except ModuleNotFoundError: execution_type = "install_prerequisites.{}".format("bat" if platform.system() == "Windows" else "sh") import mo.utils.version as v -import telemetry.telemetry as tm +try: + import openvino_telemetry as tm # pylint: disable=import-error,no-name-in-module +except ImportError: + import mo.utils.telemetry_stub as tm from mo.utils.error import classify_error_type def send_telemetry(mo_version: str, message: str, event_type: str): - t = tm.Telemetry(app_name='Model Optimizer', app_version=mo_version) - t.start_session() + t = tm.Telemetry(app_name='Version Checker', app_version=mo_version) + # do not trigger new session if we are executing from the check from within the MO because it is actually not model + # conversion run which we want to send + if execution_type != 'mo': + t.start_session(execution_type) t.send_event(execution_type, event_type, message) - t.end_session() + if execution_type != "mo": + t.end_session(execution_type) t.force_shutdown(1.0) @@ -42,16 +47,17 @@ def import_core_modules(silent: bool, path_to_module: str): :return: True if all imports were successful and False otherwise """ try: - from openvino.inference_engine import get_version, read_network # pylint: disable=import-error - from openvino.offline_transformations import ApplyMOCTransformations, ApplyLowLatencyTransformation, GenerateMappingFile # pylint: disable=import-error + from openvino.inference_engine import get_version, read_network # pylint: disable=import-error,no-name-in-module + from openvino.offline_transformations import ApplyMOCTransformations, ApplyLowLatencyTransformation, \ + GenerateMappingFile # pylint: disable=import-error,no-name-in-module - import openvino # pylint: disable=import-error + import openvino # pylint: disable=import-error,no-name-in-module if silent: return True ie_version = str(get_version()) - mo_version = str(v.get_version()) # pylint: disable=no-member + mo_version = str(v.get_version()) # pylint: disable=no-member,no-name-in-module print("\t- {}: \t{}".format("Inference Engine found in", os.path.dirname(openvino.__file__))) print("{}: \t{}".format("Inference Engine version", ie_version)) @@ -64,7 +70,8 @@ def import_core_modules(silent: bool, path_to_module: str): mo_is_custom = extracted_mo_release_version == (None, None) print("[ WARNING ] Model Optimizer and Inference Engine versions do no match.") - print("[ WARNING ] Consider building the Inference Engine Python API from sources or reinstall OpenVINO (TM) toolkit using", end=" ") + print("[ WARNING ] Consider building the Inference Engine Python API from sources or reinstall OpenVINO " + "(TM) toolkit using", end=" ") if mo_is_custom: print("\"pip install openvino\" (may be incompatible with the current Model Optimizer version)") else: diff --git a/model-optimizer/mo/utils/ie_version.py b/model-optimizer/mo/utils/ie_version.py index 7a86c55a381..dbe4a2f5ae1 100644 --- a/model-optimizer/mo/utils/ie_version.py +++ b/model-optimizer/mo/utils/ie_version.py @@ -3,7 +3,7 @@ def get_ie_version(): try: - from openvino.inference_engine import get_version # pylint: disable=import-error + from openvino.inference_engine import get_version # pylint: disable=import-error,no-name-in-module return get_version() except: return None diff --git a/model-optimizer/mo/utils/telemetry_stub.py b/model-optimizer/mo/utils/telemetry_stub.py new file mode 100644 index 00000000000..136157eb7ed --- /dev/null +++ b/model-optimizer/mo/utils/telemetry_stub.py @@ -0,0 +1,29 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + + +class Telemetry(object): + """ + Stab file for the Telemetry class which is used when Telemetry class is not available. + """ + + def __init__(self, *arg, **kwargs): + pass + + def send_event(self, *arg, **kwargs): + pass + + def send_error(self, *arg, **kwargs): + pass + + def start_session(self, *arg, **kwargs): + pass + + def end_session(self, *arg, **kwargs): + pass + + def force_shutdown(self, *arg, **kwargs): + pass + + def send_stack_trace(self, *arg, **kwargs): + pass diff --git a/model-optimizer/mo/utils/utils.py b/model-optimizer/mo/utils/utils.py index 2a4327e3267..0c153f80ded 100644 --- a/model-optimizer/mo/utils/utils.py +++ b/model-optimizer/mo/utils/utils.py @@ -44,14 +44,12 @@ def deprecated_api(class_name=None, new_method_name=None): def deprecated(func): @functools.wraps(func) def deprecation_message(*args, **kwargs): - warnings.simplefilter('always', DeprecationWarning) # turn on filter dep_msg = "Call to deprecated function {}. ".format(func.__name__) if class_name is not None: dep_msg += "Please use {}.{} method" \ "".format(class_name.__name__ if not isinstance(class_name, str) else class_name, func.__name__ if new_method_name is None else new_method_name) warnings.warn(dep_msg, DeprecationWarning, stacklevel=2) - warnings.simplefilter('default', DeprecationWarning) # reset filter return func(*args, **kwargs) return deprecation_message diff --git a/model-optimizer/telemetry/__init__.py b/model-optimizer/telemetry/__init__.py deleted file mode 100644 index 60324954ef5..00000000000 --- a/model-optimizer/telemetry/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - diff --git a/model-optimizer/telemetry/backend/__init__.py b/model-optimizer/telemetry/backend/__init__.py deleted file mode 100644 index 5c55dd8fdf2..00000000000 --- a/model-optimizer/telemetry/backend/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from .backend_ga import * diff --git a/model-optimizer/telemetry/backend/backend.py b/model-optimizer/telemetry/backend/backend.py deleted file mode 100644 index 6761fca53d4..00000000000 --- a/model-optimizer/telemetry/backend/backend.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import abc - -from telemetry.utils.message import Message - - -class BackendRegistry: - """ - The class that stores information about all registered telemetry backends - """ - r = {} - - @classmethod - def register_backend(cls, id: str, backend): - cls.r[id] = backend - - @classmethod - def get_backend(cls, id: str): - assert id in cls.r, 'The backend with id "{}" is not registered'.format(id) - return cls.r.get(id) - - -class TelemetryBackendMetaClass(abc.ABCMeta): - def __init__(cls, clsname, bases, methods): - super().__init__(clsname, bases, methods) - if cls.id is not None: - BackendRegistry.register_backend(cls.id, cls) - - -class TelemetryBackend(metaclass=TelemetryBackendMetaClass): - id = None - - @abc.abstractmethod - def __init__(self, tid: str, app_name: str, app_version: str): - """ - Initializer of the class - :param tid: database id - :param app_name: name of the application - :param app_version: version of the application - """ - - @abc.abstractmethod - def send(self, message: Message): - """ - Sends the message to the backend. - :param message: The Message object to send - :return: None - """ - - @abc.abstractmethod - def build_event_message(self, event_category: str, event_action: str, event_label: str, event_value: int = 1, - **kwargs): - """ - Should return the Message object build from the event message. - """ - - @abc.abstractmethod - def build_error_message(self, error_msg: str, **kwargs): - """ - Should return the Message object build from the error message. - """ - - @abc.abstractmethod - def build_stack_trace_message(self, error_msg: str, **kwargs): - """ - Should return the Message object build from the stack trace message. - """ - - @abc.abstractmethod - def build_session_start_message(self, **kwargs): - """ - Should return the Message object corresponding to the session start. - """ - - @abc.abstractmethod - def build_session_end_message(self, **kwargs): - """ - Should return the Message object corresponding to the session end. - """ diff --git a/model-optimizer/telemetry/backend/backend_ga.py b/model-optimizer/telemetry/backend/backend_ga.py deleted file mode 100644 index 6b4c015d9dc..00000000000 --- a/model-optimizer/telemetry/backend/backend_ga.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import uuid - -from telemetry.backend.backend import TelemetryBackend -from telemetry.utils.message import Message, MessageType -from telemetry.utils.guid import get_or_generate_uid - - -class GABackend(TelemetryBackend): - backend_url = 'https://www.google-analytics.com/collect' - id = 'ga' - - def __init__(self, tid: str = None, app_name: str = None, app_version: str = None): - super(GABackend, self).__init__(tid, app_name, app_version) - if tid is None: - tid = 'UA-17808594-29' - self.tid = tid - self.uid = get_or_generate_uid('openvino_ga_uid', lambda: str(uuid.uuid4()), is_valid_uuid4) - self.app_name = app_name - self.app_version = app_version - self.default_message_attrs = { - 'v': '1', # API Version - 'tid': self.tid, - 'cid': self.uid, - 'an': self.app_name, - 'av': self.app_version, - 'ua': 'Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14' # dummy identifier of the browser - } - - def send(self, message: Message): - try: - import requests - requests.post(self.backend_url, message.attrs, timeout=1.0) - except Exception: - pass - - def build_event_message(self, event_category: str, event_action: str, event_label: str, event_value: int = 1, - **kwargs): - data = self.default_message_attrs.copy() - data.update({ - 't': 'event', - 'ec': event_category, - 'ea': event_action, - 'el': event_label, - 'ev': event_value, - }) - return Message(MessageType.EVENT, data) - - def build_session_start_message(self, **kwargs): - data = self.default_message_attrs.copy() - data.update({ - 'sc': 'start', - 't': 'event', - 'ec': 'session', - 'ea': 'control', - 'el': 'start', - 'ev': 1, - }) - return Message(MessageType.SESSION_START, data) - - def build_session_end_message(self, **kwargs): - data = self.default_message_attrs.copy() - data.update({ - 'sc': 'end', - 't': 'event', - 'ec': 'session', - 'ea': 'control', - 'el': 'end', - 'ev': 1, - }) - return Message(MessageType.SESSION_END, data) - - def build_error_message(self, error_msg: str, **kwargs): - pass - - def build_stack_trace_message(self, error_msg: str, **kwargs): - pass - - -def is_valid_uuid4(uid: str): - try: - uuid.UUID(uid, version=4) - except ValueError: - return False - return True diff --git a/model-optimizer/telemetry/telemetry.py b/model-optimizer/telemetry/telemetry.py deleted file mode 100644 index ef882683f80..00000000000 --- a/model-optimizer/telemetry/telemetry.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import telemetry.utils.isip as isip - -from telemetry.backend.backend import BackendRegistry -from telemetry.utils.sender import TelemetrySender - - -class SingletonMetaClass(type): - def __init__(self, cls_name, super_classes, dic): - self.__single_instance = None - super().__init__(cls_name, super_classes, dic) - - def __call__(cls, *args, **kwargs): - if cls.__single_instance is None: - cls.__single_instance = super(SingletonMetaClass, cls).__call__(*args, **kwargs) - return cls.__single_instance - - -class Telemetry(metaclass=SingletonMetaClass): - """ - The main class to send telemetry data. It uses singleton pattern. The instance should be initialized with the - application name, version and tracking id just once. Later the instance can be created without parameters. - """ - def __init__(self, app_name: str = None, app_version: str = None, tid: [None, str] = None, - backend: [str, None] = 'ga'): - if not hasattr(self, 'tid'): - self.tid = None - if app_name is not None: - self.consent = isip.isip_consent() == isip.ISIPConsent.APPROVED - # override default tid - if tid is not None: - self.tid = tid - self.backend = BackendRegistry.get_backend(backend)(self.tid, app_name, app_version) - self.sender = TelemetrySender() - else: # use already configured instance - assert self.sender is not None, 'The first instantiation of the Telemetry should be done with the ' \ - 'application name and version' - - def force_shutdown(self, timeout: float = 1.0): - """ - Stops currently running threads which may be hanging because of no Internet connection. - - :param timeout: maximum timeout time - :return: None - """ - self.sender.force_shutdown(timeout) - - def send_event(self, event_category: str, event_action: str, event_label: str, event_value: int = 1, **kwargs): - """ - Send single event. - - :param event_category: category of the event - :param event_action: action of the event - :param event_label: the label associated with the action - :param event_value: the integer value corresponding to this label - :param kwargs: additional parameters - :return: None - """ - if self.consent: - self.sender.send(self.backend, self.backend.build_event_message(event_category, event_action, event_label, - event_value, **kwargs)) - - def start_session(self, **kwargs): - """ - Sends a message about starting of a new session. - - :param kwargs: additional parameters - :return: None - """ - if self.consent: - self.sender.send(self.backend, self.backend.build_session_start_message(**kwargs)) - - def end_session(self, **kwargs): - """ - Sends a message about ending of the current session. - - :param kwargs: additional parameters - :return: None - """ - if self.consent: - self.sender.send(self.backend, self.backend.build_session_end_message(**kwargs)) - - def send_error(self, error_msg: str, **kwargs): - if self.consent: - pass - - def send_stack_trace(self, stack_trace: str, **kwargs): - if self.consent: - pass diff --git a/model-optimizer/telemetry/utils/__init__.py b/model-optimizer/telemetry/utils/__init__.py deleted file mode 100644 index 60324954ef5..00000000000 --- a/model-optimizer/telemetry/utils/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - diff --git a/model-optimizer/telemetry/utils/guid.py b/model-optimizer/telemetry/utils/guid.py deleted file mode 100644 index 8bc765365ae..00000000000 --- a/model-optimizer/telemetry/utils/guid.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import os -from platform import system - -import telemetry.utils.isip as isip - - -def save_uid_to_file(file_name: str, uid: str): - """ - Save the uid to the specified file - """ - try: - # create directories recursively first - os.makedirs(os.path.dirname(file_name), exist_ok=True) - - with open(file_name, 'w') as file: - file.write(uid) - except Exception as e: - print('Failed to generate the UID file: {}'.format(str(e))) - return False - return True - - -def get_or_generate_uid(file_name: str, generator: callable, validator: [callable, None]): - """ - Get existing UID or generate a new one. - :param file_name: name of the file with the UID - :param generator: the function to generate the UID - :param validator: the function to validate the UID - :return: existing or a new UID file - """ - full_path = os.path.join(get_uid_path(), file_name) - uid = None - if os.path.exists(full_path): - with open(full_path, 'r') as file: - uid = file.readline().strip() - - if uid is not None and (validator is not None and not validator(uid)): - uid = None - - if uid is None: - uid = generator() - save_uid_to_file(full_path, uid) - return uid - - -def get_uid_path(): - """ - Returns a directory with the the OpenVINO randomly generated UUID file. - - :return: the directory with the the UUID file - """ - platform = system() - subdir = None - if platform == 'Windows': - subdir = 'Intel Corporation' - elif platform in ['Linux', 'Darwin']: - subdir = '.intel' - if subdir is None: - raise Exception('Failed to determine the operation system type') - - return os.path.join(isip.isip_consent_base_dir(), subdir) diff --git a/model-optimizer/telemetry/utils/isip.py b/model-optimizer/telemetry/utils/isip.py deleted file mode 100644 index 9475ce381fa..00000000000 --- a/model-optimizer/telemetry/utils/isip.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import os -from enum import Enum -from platform import system - - -class ISIPConsent(Enum): - APPROVED = 0 - DECLINED = 1 - UNKNOWN = 2 - - -def isip_consent_base_dir(): - """ - Returns the base directory with the ISIP consent file. The full directory may not have write access on Linux/OSX - systems so that is why the base directory is used. - :return: - """ - platform = system() - - dir_to_check = None - - if platform == 'Windows': - dir_to_check = '$LOCALAPPDATA' - elif platform in ['Linux', 'Darwin']: - dir_to_check = '$HOME' - - if dir_to_check is None: - raise Exception('Failed to find location of the ISIP consent') - - return os.path.expandvars(dir_to_check) - - -def _isip_consent_sub_directory(): - platform = system() - if platform == 'Windows': - return 'Intel Corporation' - elif platform in ['Linux', 'Darwin']: - return 'intel' - raise Exception('Failed to find location of the ISIP consent') - - -def _isip_consent_dir(): - dir_to_check = os.path.join(isip_consent_base_dir(), _isip_consent_sub_directory()) - return os.path.expandvars(dir_to_check) - - -def _isip_consent_file(): - return os.path.join(_isip_consent_dir(), 'isip') - - -def isip_consent(): - file_to_check = _isip_consent_file() - if not os.path.exists(file_to_check): - return ISIPConsent.UNKNOWN - - try: - with open(file_to_check, 'r') as file: - content = file.readline().strip() - if content == '1': - return ISIPConsent.APPROVED - else: - return ISIPConsent.DECLINED - except Exception as e: - pass - - # unknown value in the file is considered as a unknown consent - return ISIPConsent.UNKNOWN diff --git a/model-optimizer/telemetry/utils/message.py b/model-optimizer/telemetry/utils/message.py deleted file mode 100644 index a6ea1b4f643..00000000000 --- a/model-optimizer/telemetry/utils/message.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from enum import Enum - - -class MessageType(Enum): - EVENT = 0 - ERROR = 1 - STACK_TRACE = 2 - SESSION_START = 3 - SESSION_END = 4 - - -class Message: - def __init__(self, type: MessageType, attrs: dict): - self.type = type - self.attrs = attrs.copy() diff --git a/model-optimizer/telemetry/utils/sender.py b/model-optimizer/telemetry/utils/sender.py deleted file mode 100644 index f3f456ce4de..00000000000 --- a/model-optimizer/telemetry/utils/sender.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import threading -from concurrent import futures -from time import sleep - -from telemetry.backend.backend import TelemetryBackend -from telemetry.utils.message import Message - -MAX_QUEUE_SIZE = 1000 - - -class TelemetrySender: - def __init__(self, max_workers=None): - self.executor = futures.ThreadPoolExecutor(max_workers=max_workers) - self.queue_size = 0 - self._lock = threading.Lock() - - def send(self, backend: TelemetryBackend, message: Message): - def _future_callback(future): - with self._lock: - self.queue_size -= 1 - - free_space = False - with self._lock: - if self.queue_size < MAX_QUEUE_SIZE: - free_space = True - self.queue_size += 1 - else: - pass # dropping a message because the queue is full - # to avoid dead lock we should not add callback inside the "with self._lock" block because it will be executed - # immediately if the fut is available - if free_space: - fut = self.executor.submit(backend.send, message) - fut.add_done_callback(_future_callback) - - def force_shutdown(self, timeout: float): - """ - Forces all threads to be stopped after timeout. The "shutdown" method of the ThreadPoolExecutor removes only not - yet scheduled threads and keep running the existing one. In order to stop the already running use some low-level - attribute. The operation with low-level attributes is wrapped with the try/except to avoid potential crash if - these attributes will removed or renamed. - - :param timeout: timeout to wait before the shutdown - :return: None - """ - try: - need_sleep = False - with self._lock: - if self.queue_size > 0: - need_sleep = True - if need_sleep: - sleep(timeout) - self.executor.shutdown(wait=False) - self.executor._threads.clear() - futures.thread._threads_queues.clear() - except Exception: - pass diff --git a/model-optimizer/unit_tests/mo/bom_test.py b/model-optimizer/unit_tests/mo/bom_test.py index 0bb7118e2a0..b3e2295372c 100644 --- a/model-optimizer/unit_tests/mo/bom_test.py +++ b/model-optimizer/unit_tests/mo/bom_test.py @@ -16,7 +16,7 @@ full_name_patterns_to_skip = ['^mo/utils/convert.py$', ] if platform.system() == 'Windows': full_name_patterns_to_skip = [i.replace('/', '\\\\') for i in full_name_patterns_to_skip] -dirs_to_search = ['mo', 'extensions', 'tf_call_ie_layer', 'telemetry'] +dirs_to_search = ['mo', 'extensions'] def is_match(name: str, patterns: ()): From 56bff02a8beb24ed4ae5ef68f255d9177453c236 Mon Sep 17 00:00:00 2001 From: Edward Shogulin Date: Sat, 15 May 2021 08:48:00 +0300 Subject: [PATCH 80/99] [LPT] [CPU] Convert dequantization shift in low precision before FP32 conversion in CPU (#5247) * [LPT] [CPU] Convert dequantization shift in low precision before FP32 conversion in CPU * [LPT] Avoid not neccessary conversion to FP32 * [LPT] Split workaround: replace_node manual handling * [nGraph] [LPT] Q/DQ representation on weights extension: update transformation for conversion to old format * review notes fix * [LPT] checkZeroPoint reuse --- .../convert_subtract_constant.hpp | 27 ++ .../low_precision/layer_transformation.hpp | 8 + .../include/low_precision/network_helper.hpp | 2 + .../src/convert_subtract_constant.cpp | 98 ++++++ .../src/convolution.cpp | 4 +- .../src/fake_quantize.cpp | 15 +- .../src/fold_convert.cpp | 25 +- .../src/fuse_convert.cpp | 2 +- .../src/fuse_fake_quantize.cpp | 8 +- .../src/fuse_multiply_to_fake_quantize.cpp | 10 +- .../src/fuse_subtract_to_fake_quantize.cpp | 10 +- .../src/mat_mul.cpp | 4 +- .../src/multiply.cpp | 4 +- .../src/multiply_to_group_convolution.cpp | 2 +- .../src/network_helper.cpp | 64 ++-- .../pull_reshape_through_dequantization.cpp | 26 +- .../pull_transpose_through_dequantization.cpp | 24 +- .../src/split.cpp | 7 +- .../src/subtract_multiply_to_multiply_add.cpp | 4 +- .../src/mkldnn_plugin/mkldnn_plugin.cpp | 6 + ...nvert_subtract_constant_transformation.cpp | 333 ++++++++++++++++++ .../fold_convert_transformation.cpp | 41 +++ .../group_convolution_transformation.cpp | 11 +- .../layer_transformation.cpp | 6 +- ..._through_dequantization_transformation.cpp | 98 ++++++ .../convert_quantize_dequantize.cpp | 151 ++++++-- .../src/common/builders.cpp | 17 +- 27 files changed, 892 insertions(+), 115 deletions(-) create mode 100644 inference-engine/src/low_precision_transformations/include/low_precision/convert_subtract_constant.hpp create mode 100644 inference-engine/src/low_precision_transformations/src/convert_subtract_constant.cpp create mode 100644 inference-engine/tests/functional/inference_engine/lp_transformations/convert_subtract_constant_transformation.cpp diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/convert_subtract_constant.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/convert_subtract_constant.hpp new file mode 100644 index 00000000000..ea2219df6e5 --- /dev/null +++ b/inference-engine/src/low_precision_transformations/include/low_precision/convert_subtract_constant.hpp @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include +#include + +namespace ngraph { +namespace pass { +namespace low_precision { + +class TRANSFORMATIONS_API ConvertSubtractConstant; + +} // namespace low_precision +} // namespace pass +} // namespace ngraph + +class ngraph::pass::low_precision::ConvertSubtractConstant : public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + ConvertSubtractConstant(const std::vector& constantPrecisions = {}); +}; diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp index 54fadb9d738..36b1293cd42 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp @@ -70,6 +70,10 @@ public: return -1.0e15f; } else if (precision == element::f32) { return std::numeric_limits::lowest(); + } else if (precision == element::i4) { + return -8.f; + } else if (precision == element::u4) { + return 0.f; } else { NGRAPH_CHECK(false, "unexpected precision ", precision); } @@ -88,6 +92,10 @@ public: return 1.0e15f; } else if (precision == element::f32) { return std::numeric_limits::max(); + } else if (precision == element::i4) { + return 7.f; + } else if (precision == element::u4) { + return 15.f; } else { THROW_TRANSFORMATION_EXCEPTION << "unexpected precision " << precision; } diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp index dcd10d224e7..9846ef50d6a 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp @@ -255,6 +255,8 @@ std::shared_ptr fold(Args&&... args) { return node; } +std::shared_ptr foldConvert(const Output& node, const element::Type targetPrecision); + template std::shared_ptr fold_reshape(Args&&... args) { std::shared_ptr node = std::make_shared(std::forward(args)...); diff --git a/inference-engine/src/low_precision_transformations/src/convert_subtract_constant.cpp b/inference-engine/src/low_precision_transformations/src/convert_subtract_constant.cpp new file mode 100644 index 00000000000..8bf38985309 --- /dev/null +++ b/inference-engine/src/low_precision_transformations/src/convert_subtract_constant.cpp @@ -0,0 +1,98 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "low_precision/convert_subtract_constant.hpp" + +#include +#include + +#include +#include +#include "low_precision/network_helper.hpp" + +using namespace ngraph; + +NGRAPH_RTTI_DEFINITION(ngraph::pass::low_precision::ConvertSubtractConstant, "ConvertSubtractConstant", 0); + +// Original (FP16 as example, I8 in constantPrecisions): +// +// Constant +// | I8 +// Convert Constant +// \ FP16 / FP16 +// Subtract Constant +// \ FP16 / FP16 +// Multiply +// +// Result: +// +// Constant Constant +// | I8 | I8 +// Convert Convert +// \ FP16 / FP16 +// Subtract Constant +// \ FP16 / FP16 +// Multiply +// +ngraph::pass::low_precision::ConvertSubtractConstant::ConvertSubtractConstant(const std::vector& constantPrecisions) { + auto weightsConstantWrapper = ngraph::pattern::wrap_type(pattern::consumers_count(1)); + auto weightsConvertWrapper = ngraph::pattern::wrap_type({ weightsConstantWrapper }, pattern::consumers_count(1)); + auto subtractConstantWrapper = ngraph::pattern::wrap_type(pattern::consumers_count(1)); + auto subtractWrapper = ngraph::pattern::wrap_type({ weightsConvertWrapper, subtractConstantWrapper }, pattern::consumers_count(1)); + auto multiplyConstantWrapper = ngraph::pattern::wrap_type(pattern::consumers_count(1)); + auto multiplyWrapper = ngraph::pattern::wrap_type({ subtractWrapper, multiplyConstantWrapper }, pattern::consumers_count(1)); + + ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher & m) -> bool { + const auto& opsMap = m.get_pattern_value_map(); + const auto weightsConvert = opsMap.at(weightsConvertWrapper).get_node_shared_ptr(); + const auto quantizePrecision = weightsConvert->get_input_element_type(0); + const auto dequantizationPrecision = weightsConvert->get_output_element_type(0); + + // validation by Convert operation input precisions + if (!constantPrecisions.empty()) { + const ngraph::element::Type inputPrecision = quantizePrecision; + if (std::find(constantPrecisions.begin(), constantPrecisions.end(), inputPrecision) == constantPrecisions.end()) { + return false; + } + } + + const auto subtract = opsMap.at(subtractWrapper).get_node_shared_ptr(); + if (!NetworkHelper::checkZeroPoint(subtract)) { + return false; + } + + const auto subtractConstant = opsMap.at(subtractConstantWrapper).get_node_shared_ptr(); + auto resultSubtractConstant = NetworkHelper::round(subtractConstant, quantizePrecision); + if (NetworkHelper::isScalarLike(resultSubtractConstant)) { + resultSubtractConstant = NetworkHelper::toScalar(resultSubtractConstant); + if (op::util::constantIsEqualTo(resultSubtractConstant, 0.f)) { + resultSubtractConstant = nullptr; + } + } + + if (resultSubtractConstant == nullptr) { + const auto multiply = opsMap.at(multiplyWrapper).get_node_shared_ptr(); + const auto newMultiply = std::make_shared(weightsConvert, opsMap.at(multiplyConstantWrapper).get_node_shared_ptr()); + NetworkHelper::copyInfo(multiply, newMultiply); + replace_node(multiply, newMultiply); + } else { + NetworkHelper::copyInfo(subtractConstant, resultSubtractConstant); + const auto resultConvert = std::make_shared(resultSubtractConstant, dequantizationPrecision); + NetworkHelper::copyInfo(subtractConstant, resultConvert); + resultConvert->set_friendly_name(subtractConstant->get_friendly_name() + "/Convert"); + + auto& rtInfo = resultConvert->get_rt_info(); + rtInfo["DISABLED_CONSTANT_FOLDING"] = std::make_shared>(""); + + const auto newSubtract = std::make_shared(opsMap.at(weightsConvertWrapper).get_node_shared_ptr(), resultConvert); + NetworkHelper::copyInfo(subtract, newSubtract); + replace_node(subtract, newSubtract); + } + + return true; + }; + + auto m = std::make_shared(multiplyWrapper, "ConvertSubtractConstant"); + this->register_matcher(m, callback); +} diff --git a/inference-engine/src/low_precision_transformations/src/convolution.cpp b/inference-engine/src/low_precision_transformations/src/convolution.cpp index 020c8d3d070..ff5ca944df5 100644 --- a/inference-engine/src/low_precision_transformations/src/convolution.cpp +++ b/inference-engine/src/low_precision_transformations/src/convolution.cpp @@ -79,6 +79,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph const auto newSubtract = as_type_ptr(subtract->clone_with_new_inputs({ subtract->input_value(0).get_node_shared_ptr(), newShift })); + NetworkHelper::copyInfo(subtract, newSubtract); replace_node(subtract, newSubtract); newSubtract->set_output_type(0, subtract->get_output_element_type(0), newSubtract->get_output_partial_shape(0)); @@ -203,7 +204,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph reshapeFromWeights : multiplyFromWeights->input_value(0) }), - fold( + foldConvert( fold_reshape( multiplyFromWeights->input_value(1), std::make_shared(element::u64, Shape{ newScaleShape.size() }, newScaleShape), @@ -230,6 +231,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph auto zeroPointConstant = fold( subtractFromWeights->get_input_node_shared_ptr(1), std::make_shared(element::i32, Shape{ zeroPointShape.size() }, zeroPointShape)); + NetworkHelper::copyInfo(subtractFromWeights->get_input_node_shared_ptr(1), zeroPointConstant); replace_node(subtractFromWeights->get_input_node_shared_ptr(1), zeroPointConstant); } } diff --git a/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp index 8edf710623a..41b9851d5e3 100644 --- a/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp @@ -114,15 +114,14 @@ std::shared_ptr FakeQuantizeTransformation::fuseElementwis const std::shared_ptr& fakeQuantize) const { const std::shared_ptr eltwise = fakeQuantize->get_input_node_shared_ptr(0); - std::shared_ptr inputLowConst_f32 = fold(fakeQuantize->get_input_node_shared_ptr(1), deqPrecision); - std::shared_ptr inputHighConst_f32 = fold(fakeQuantize->get_input_node_shared_ptr(2), deqPrecision); - + std::shared_ptr inputLowConst_f32 = foldConvert(fakeQuantize->get_input_node_shared_ptr(1), deqPrecision); + std::shared_ptr inputHighConst_f32 = foldConvert(fakeQuantize->get_input_node_shared_ptr(2), deqPrecision); std::shared_ptr constant = fq::getConstant(eltwise); if (is_type(eltwise) && checkElementwise(eltwise)) { const auto value = constant->get_output_element_type(0) == deqPrecision ? constant : - fold(constant, deqPrecision); + foldConvert(constant, deqPrecision); const auto valueVec = as_type_ptr(value)->cast_vector(); @@ -144,7 +143,7 @@ std::shared_ptr FakeQuantizeTransformation::fuseElementwis } else if (is_type(eltwise) && checkElementwise(eltwise)) { const auto value = constant->get_output_element_type(0) == deqPrecision ? constant : - fold(constant, deqPrecision); + foldConvert(constant, deqPrecision); inputLowConst_f32 = fq::updateShape(fold(inputLowConst_f32, value), fakeQuantize->get_output_shape(0)); inputHighConst_f32 = fq::updateShape(fold(inputHighConst_f32, value), fakeQuantize->get_output_shape(0)); @@ -156,7 +155,7 @@ std::shared_ptr FakeQuantizeTransformation::fuseElementwis const auto value = constant->get_output_element_type(0) == deqPrecision ? constant : - fold(constant, deqPrecision); + foldConvert(constant, deqPrecision); inputLowConst_f32 = fq::updateShape(fold(inputLowConst_f32, value), fakeQuantize->get_output_shape(0)); inputHighConst_f32 = fq::updateShape(fold(inputHighConst_f32, value), fakeQuantize->get_output_shape(0)); @@ -176,8 +175,8 @@ std::shared_ptr FakeQuantizeTransformation::fuseElementwis data->output(outputIdx), inputLowConst_f32, inputHighConst_f32, - fold(fakeQuantize->input_value(3), deqPrecision), - fold(fakeQuantize->input_value(4), deqPrecision) })); + foldConvert(fakeQuantize->input_value(3), deqPrecision), + foldConvert(fakeQuantize->input_value(4), deqPrecision) })); replace_node(fakeQuantize, newFakeQuantize); ngraph::copy_runtime_info({ fakeQuantize, eltwise }, newFakeQuantize); diff --git a/inference-engine/src/low_precision_transformations/src/fold_convert.cpp b/inference-engine/src/low_precision_transformations/src/fold_convert.cpp index 43aaa9771d4..091380442b8 100644 --- a/inference-engine/src/low_precision_transformations/src/fold_convert.cpp +++ b/inference-engine/src/low_precision_transformations/src/fold_convert.cpp @@ -22,18 +22,31 @@ bool FoldConvertTransformation::transform(TransformationContext& context, ngraph return false; } - const auto convert = subtract->get_input_node_shared_ptr(1); - const auto resultConstant = fold(convert->get_input_node_shared_ptr(0), convert->output(0).get_element_type()); + auto foldConvert = [&](const size_t branch) { + const auto convert = subtract->get_input_node_shared_ptr(branch); + if (!is_type(convert) || !is_type(convert->get_input_node_shared_ptr(0))) { + return; + } + + const auto resultConstant = ngraph::pass::low_precision::foldConvert(convert->get_input_node_shared_ptr(0), convert->output(0).get_element_type()); + assert(is_type(resultConstant)); + + replace_node(convert, resultConstant); + updateOutput(context, resultConstant, convert); + }; + + foldConvert(0ul); + foldConvert(1ul); - replace_node(convert, resultConstant); - updateOutput(context, resultConstant, convert); return true; } bool FoldConvertTransformation::canBeTransformed(const TransformationContext& context, std::shared_ptr operation) const { return - is_type(operation->get_input_node_ptr(1)) && - is_type(operation->get_input_node_ptr(1)->get_input_node_ptr(0)); + (is_type(operation->get_input_node_ptr(1)) && + is_type(operation->get_input_node_ptr(1)->get_input_node_ptr(0))) || + (is_type(operation->get_input_node_ptr(0)) && + is_type(operation->get_input_node_ptr(0)->get_input_node_ptr(0))); } bool FoldConvertTransformation::isPrecisionPreserved(std::shared_ptr layer) const noexcept { diff --git a/inference-engine/src/low_precision_transformations/src/fuse_convert.cpp b/inference-engine/src/low_precision_transformations/src/fuse_convert.cpp index fba86ef6c60..38aa2133940 100644 --- a/inference-engine/src/low_precision_transformations/src/fuse_convert.cpp +++ b/inference-engine/src/low_precision_transformations/src/fuse_convert.cpp @@ -60,7 +60,7 @@ bool FuseConvertTransformation::transform(TransformationContext& context, ngraph std::shared_ptr parent = convert->get_input_node_shared_ptr(0); if (is_type(parent)) { - auto convertedConstant = fold(parent, convert->get_convert_element_type()); + auto convertedConstant = foldConvert(parent, convert->get_convert_element_type()); NetworkHelper::copyInfo(parent, convertedConstant); replace_node(convert, convertedConstant); } else { diff --git a/inference-engine/src/low_precision_transformations/src/fuse_fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fuse_fake_quantize.cpp index dfca1b164ef..6ef45c0b6ca 100644 --- a/inference-engine/src/low_precision_transformations/src/fuse_fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fuse_fake_quantize.cpp @@ -102,21 +102,21 @@ std::shared_ptr FuseFakeQuantizeTransformation::handle( if (is_type(eltwise) && fuse_fq::eltwiseWithConstant(eltwise)) { const auto value = constant->get_output_element_type(0) == eltwise->get_output_element_type(0) ? constant : - fold(constant, eltwise->get_output_element_type(0)); + foldConvert(constant, eltwise->get_output_element_type(0)); inputLowConst = fuse_fq::updateShape(fold(inputLowConst, value), fakeQuantize->get_output_shape(0)); inputHightConst = fuse_fq::updateShape(fold(inputHightConst, value), fakeQuantize->get_output_shape(0)); } else if (is_type(eltwise) && fuse_fq::eltwiseWithConstant(eltwise)) { const auto value = constant->get_output_element_type(0) == eltwise->get_output_element_type(0) ? constant : - fold(constant, eltwise->get_output_element_type(0)); + foldConvert(constant, eltwise->get_output_element_type(0)); inputLowConst = fuse_fq::updateShape(fold(inputLowConst, value), fakeQuantize->get_output_shape(0)); inputHightConst = fuse_fq::updateShape(fold(inputHightConst, value), fakeQuantize->get_output_shape(0)); } else if (is_type(eltwise) && fuse_fq::eltwiseWithConstant(eltwise)) { const auto value = constant->get_output_element_type(0) == eltwise->get_output_element_type(0) ? constant : - fold(constant, eltwise->get_output_element_type(0)); + foldConvert(constant, eltwise->get_output_element_type(0)); inputLowConst = fuse_fq::updateShape(fold(inputLowConst, value), fakeQuantize->get_output_shape(0)); inputHightConst = fuse_fq::updateShape(fold(inputHightConst, value), fakeQuantize->get_output_shape(0)); @@ -128,7 +128,7 @@ std::shared_ptr FuseFakeQuantizeTransformation::handle( const auto value = constant->get_output_element_type(0) == eltwise->get_output_element_type(0) ? constant : - fold(constant, eltwise->get_output_element_type(0)); + foldConvert(constant, eltwise->get_output_element_type(0)); inputLowConst = fuse_fq::updateShape(fold(inputLowConst, value), fakeQuantize->get_output_shape(0)); inputHightConst = fuse_fq::updateShape(fold(inputHightConst, value), fakeQuantize->get_output_shape(0)); diff --git a/inference-engine/src/low_precision_transformations/src/fuse_multiply_to_fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fuse_multiply_to_fake_quantize.cpp index 02448aa6dcc..c1b7f4e907b 100644 --- a/inference-engine/src/low_precision_transformations/src/fuse_multiply_to_fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fuse_multiply_to_fake_quantize.cpp @@ -32,12 +32,12 @@ bool FuseMultiplyToFakeQuantizeTransformation::transform(TransformationContext& const auto multiplyConstant = multiply->get_input_node_shared_ptr(1); - auto outputLowConst_f32 = fold(fakeQuantize->get_input_node_shared_ptr(3), deqPrecision); - auto outputHighConst_f32 = fold(fakeQuantize->get_input_node_shared_ptr(4), deqPrecision); + auto outputLowConst_f32 = foldConvert(fakeQuantize->get_input_node_shared_ptr(3), deqPrecision); + auto outputHighConst_f32 = foldConvert(fakeQuantize->get_input_node_shared_ptr(4), deqPrecision); const auto value = multiplyConstant->get_output_element_type(0) == element::f32 ? multiplyConstant : - fold(multiplyConstant, deqPrecision); + foldConvert(multiplyConstant, deqPrecision); outputLowConst_f32 = fold(outputLowConst_f32, value); outputHighConst_f32 = fold(outputHighConst_f32, value); @@ -48,8 +48,8 @@ bool FuseMultiplyToFakeQuantizeTransformation::transform(TransformationContext& auto newFakeQuantize = std::make_shared>( opset1::FakeQuantize( fakeQuantizeParent->output(parentIndex), - fold(fakeQuantize->input_value(1), deqPrecision), - fold(fakeQuantize->input_value(2), deqPrecision), + foldConvert(fakeQuantize->input_value(1), deqPrecision), + foldConvert(fakeQuantize->input_value(2), deqPrecision), outputLowConst_f32, outputHighConst_f32, fakeQuantize->get_levels()), diff --git a/inference-engine/src/low_precision_transformations/src/fuse_subtract_to_fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fuse_subtract_to_fake_quantize.cpp index 6629bccc3c5..2e3f2e23d3f 100644 --- a/inference-engine/src/low_precision_transformations/src/fuse_subtract_to_fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fuse_subtract_to_fake_quantize.cpp @@ -32,12 +32,12 @@ bool FuseSubtractToFakeQuantizeTransformation::transform(TransformationContext& const auto subtractConstant = subtract->get_input_node_shared_ptr(1); - auto outputLowConst_f32 = fold(fakeQuantize->get_input_node_shared_ptr(3), deqPrecision); - auto outputHighConst_f32 = fold(fakeQuantize->get_input_node_shared_ptr(4), deqPrecision); + auto outputLowConst_f32 = foldConvert(fakeQuantize->get_input_node_shared_ptr(3), deqPrecision); + auto outputHighConst_f32 = foldConvert(fakeQuantize->get_input_node_shared_ptr(4), deqPrecision); const auto value = subtractConstant->get_output_element_type(0) == element::f32 ? subtractConstant : - fold(subtractConstant, deqPrecision); + foldConvert(subtractConstant, deqPrecision); outputLowConst_f32 = fold(outputLowConst_f32, value); outputHighConst_f32 = fold(outputHighConst_f32, value); @@ -48,8 +48,8 @@ bool FuseSubtractToFakeQuantizeTransformation::transform(TransformationContext& auto newFakeQuantize = std::make_shared>( opset1::FakeQuantize( fakeQuantizeParent->output(parentIndex), - fold(fakeQuantize->input_value(1), deqPrecision), - fold(fakeQuantize->input_value(2), deqPrecision), + foldConvert(fakeQuantize->input_value(1), deqPrecision), + foldConvert(fakeQuantize->input_value(2), deqPrecision), outputLowConst_f32, outputHighConst_f32, fakeQuantize->get_levels()), diff --git a/inference-engine/src/low_precision_transformations/src/mat_mul.cpp b/inference-engine/src/low_precision_transformations/src/mat_mul.cpp index edc7d84bfcb..7d22bb30467 100644 --- a/inference-engine/src/low_precision_transformations/src/mat_mul.cpp +++ b/inference-engine/src/low_precision_transformations/src/mat_mul.cpp @@ -80,7 +80,7 @@ bool MatMulTransformation::transform(TransformationContext &context, ngraph::pat // multiply by weights: [1, ..., 1, Y] x [Y, Z] => [1, ..., 1, Z] const auto newSubConst = NetworkHelper::toScalarIfPossible(fold( broadcastedConst, - fold(newMatMul->get_input_node_shared_ptr(1), newMatMul->get_element_type()), + foldConvert(newMatMul->get_input_node_shared_ptr(1), newMatMul->get_element_type()), newMatMul->get_transpose_a(), newMatMul->get_transpose_b())); @@ -128,7 +128,7 @@ bool MatMulTransformation::transform(TransformationContext &context, ngraph::pat const auto newMulConst = NetworkHelper::toScalarIfPossible(fold( mulConst1, - fold(mulConst2, element::f32))); + foldConvert(mulConst2, element::f32))); const auto newMultiply = std::make_shared>( std::vector{ deqPrecision, deqPrecision }, diff --git a/inference-engine/src/low_precision_transformations/src/multiply.cpp b/inference-engine/src/low_precision_transformations/src/multiply.cpp index 0094a283fb9..bf354bfc5f0 100644 --- a/inference-engine/src/low_precision_transformations/src/multiply.cpp +++ b/inference-engine/src/low_precision_transformations/src/multiply.cpp @@ -74,8 +74,8 @@ bool MultiplyTransformation::transform(TransformationContext& context, ngraph::p ngraph::op::TemporaryReplaceOutputType(multiplyParentParent, element::f32).get(), ngraph::op::TemporaryReplaceOutputType( fold( - fold(multiplyParentConst, element::f32), - fold(constParent, element::f32)), + foldConvert(multiplyParentConst, element::f32), + foldConvert(constParent, element::f32)), element::f32).get()); NetworkHelper::copyInfo(multiplyParent.get_node_shared_ptr(), newMultiply); diff --git a/inference-engine/src/low_precision_transformations/src/multiply_to_group_convolution.cpp b/inference-engine/src/low_precision_transformations/src/multiply_to_group_convolution.cpp index d0949f5353e..b6bd28272d9 100644 --- a/inference-engine/src/low_precision_transformations/src/multiply_to_group_convolution.cpp +++ b/inference-engine/src/low_precision_transformations/src/multiply_to_group_convolution.cpp @@ -91,7 +91,7 @@ bool MultiplyToGroupConvolutionTransformation::transform(TransformationContext& if (dequantization.subtract != nullptr) { lastNode = std::make_shared( convolution, - fold(fold(dequantization.subtractConstant, element::f32))); + fold(foldConvert(dequantization.subtractConstant, element::f32))); lastNode->set_friendly_name(convolution->get_friendly_name() + "/Add"); } diff --git a/inference-engine/src/low_precision_transformations/src/network_helper.cpp b/inference-engine/src/low_precision_transformations/src/network_helper.cpp index 59e622b35ca..dbca7606e73 100644 --- a/inference-engine/src/low_precision_transformations/src/network_helper.cpp +++ b/inference-engine/src/low_precision_transformations/src/network_helper.cpp @@ -262,11 +262,11 @@ std::shared_ptr NetworkHelper::swapMultiplyAndAdd(std::shared_ptrget_output_shape(0) : a->get_output_shape(0), bDivAValues); } else { - b = fold(b, element::f32); - a = fold(a, element::f32); + b = foldConvert(b, element::f32); + a = foldConvert(a, element::f32); bDivA = fold(b, a); // TODO: issue #49868 - bDivA = fold(bDivA, a->get_output_element_type(0)); + bDivA = foldConvert(bDivA, a->get_output_element_type(0)); } OutputVector inputs{ {}, {} }; @@ -451,7 +451,7 @@ FakeQuantizeDequantization NetworkHelper::foldDequantization(const std::shared_p } if (dequantization.convert != nullptr) { - const std::shared_ptr result = fold(dequantization.data, dequantization.convert->get_element_type()); + const std::shared_ptr result = foldConvert(dequantization.data, dequantization.convert->get_element_type()); if (is_type(result)) { if (inPlace) { copyInfo(dequantization.convert, result); @@ -467,7 +467,7 @@ FakeQuantizeDequantization NetworkHelper::foldDequantization(const std::shared_p } if (dequantization.subtractConvert != nullptr) { - const auto convertionResult = fold( + const auto convertionResult = foldConvert( dequantization.subtractConstant, dequantization.subtractConvert->get_element_type()); if (is_type(convertionResult)) { @@ -502,7 +502,7 @@ FakeQuantizeDequantization NetworkHelper::foldDequantization(const std::shared_p return dequantization; } if (dequantization.multiply->get_output_element_type(0) != result->get_element_type()) { - result = fold(result, dequantization.multiply->get_output_element_type(0)); + result = foldConvert(result, dequantization.multiply->get_output_element_type(0)); } if (inPlace) { copyInfo(dequantization.multiply, result); @@ -609,16 +609,16 @@ std::shared_ptr NetworkHelper::foldFakeQuantize( if (type1.is_real() && !type2.is_real()) { return fold( fq->input_value(0), - fold(fq->input_value(3), type1)); + foldConvert(fq->input_value(3), type1)); } if (!type1.is_real() && type2.is_real()) { return fold( - fold(fq->input_value(0), type2), + foldConvert(fq->input_value(0), type2), fq->input_value(3)); } return fold( - fold(fq->input_value(0), element::f32), - fold(fq->input_value(3), element::f32)); + foldConvert(fq->input_value(0), element::f32), + foldConvert(fq->input_value(3), element::f32)); } auto constant = as_type_ptr(fq->get_input_node_shared_ptr(0)); @@ -755,7 +755,7 @@ std::shared_ptr NetworkHelper::composeFakeQuantize(const s if (dequantization.subtract != nullptr) { const auto subtractValue = (dequantization.subtractConvert == nullptr) ? dequantization.subtractConstant : - fold(dequantization.subtractConstant, dequantization.subtractConvert->output(0).get_element_type()); + foldConvert(dequantization.subtractConstant, dequantization.subtractConvert->output(0).get_element_type()); const std::shared_ptr replacement = std::make_shared>( newFakeQuantize->input_value(0), @@ -782,11 +782,11 @@ std::shared_ptr NetworkHelper::composeFakeQuantize(const s assert((precision2.is_real() == precision1.is_real()) && (precision2.bitwidth() >= precision1.bitwidth())); auto output = fold( - precision2 != precision1 ? fold(value1, precision2) : value1, + precision2 != precision1 ? foldConvert(value1, precision2) : value1, value2); if (output->output(0).get_element_type() != precision1) { - output = fold(output, precision1); + output = foldConvert(output, precision1); } return output; @@ -907,7 +907,7 @@ std::tuple, std::shared_ptr> NetworkHelper::decompos std::shared_ptr newFqConstant = as_type_ptr(newFQ); if (is_type(newFQ)) { - convert = fold(newFQ, precision); + convert = foldConvert(newFQ, precision); } else if (is_type(newFQ)) { newFQ = setOutDataPrecision(as_type_ptr(newFQ), precision); convert = newFQ; @@ -1032,13 +1032,13 @@ FakeQuantizeDequantization NetworkHelper::createDequantizationFromFakeQuantize( // TODO: threshold values have to used here to avoid shifts - const std::shared_ptr scale = as_type_ptr(fold(fold( + const std::shared_ptr scale = as_type_ptr(foldConvert(fold( fold(outputHigh, outputLow), fold(newMax, newMin)), deqPrecision)); assert(scale != nullptr); std::shared_ptr shift = hasZeroPoint ? - as_type_ptr(fold(fold( + as_type_ptr(foldConvert(fold( fold(fold(newMin, outputHigh), fold(newMax, outputLow)), fold(outputHigh, outputLow)), deqPrecision)) : nullptr; @@ -1298,7 +1298,7 @@ FakeQuantizeDequantizationValues NetworkHelper::createEmptyValues(const FakeQuan std::shared_ptr subtract1Const = dequantization.subtract ? (dequantization.subtractConvert == nullptr ? dequantization.subtractConstant->clone_with_new_inputs({}) : - fold(dequantization.subtractConstant, dequantization.subtractConvert->get_element_type())) : + foldConvert(dequantization.subtractConstant, dequantization.subtractConvert->get_element_type())) : std::make_shared(parent->get_output_element_type(0), Shape({}), std::vector({ 0.f })); subtract1Const->set_output_type(0, multiply1Const->get_output_element_type(0), subtract1Const->get_output_partial_shape(0)); @@ -1357,6 +1357,8 @@ std::shared_ptr NetworkHelper::optimizeSubtract(std::shared_ptr>(data, roundedShift); NetworkHelper::copyInfo(subtract, replacement); @@ -1364,22 +1366,10 @@ std::shared_ptr NetworkHelper::optimizeSubtract(std::shared_ptrinput_value(0).get_node_shared_ptr()); - // replacement = nullptr; - // } - // } - return replacement; - } else if (is_type(subtractParent) || is_type(subtractParent->get_input_node_shared_ptr(0))) { + } else if (is_type(subtractParent) && is_type(subtractParent->get_input_node_shared_ptr(0))) { auto replacement = std::make_shared>(data, subtractParent->get_input_node_shared_ptr(0)); + NetworkHelper::copyInfo(subtract, replacement); NetworkHelper::setOutDataPrecisionForTypeRelaxed(replacement, convertOutputType); replace_node(subtract, replacement); return replacement; @@ -1453,7 +1443,7 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter parent, dequantization.subtractConstant->output(0).get_element_type() == parentPrecision ? dequantization.subtractConstant : - fold(dequantization.subtractConstant, parentPrecision)); + foldConvert(dequantization.subtractConstant, parentPrecision)); ngraph::copy_runtime_info({ newOperation, parent }, parent); } else { parent = std::make_shared(parent, dequantization.subtractConvert); @@ -1474,7 +1464,7 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter DequantizationMultiply(parent, multiplyConstant->output(0).get_element_type() == parentPrecision ? multiplyConstant : - fold(multiplyConstant->output(0), parentPrecision)), + foldConvert(multiplyConstant->output(0), parentPrecision)), dequantization.multiply->get_output_element_type(0)); ngraph::copy_runtime_info({ newOperation, parent }, parent); } @@ -1541,6 +1531,14 @@ std::shared_ptr NetworkHelper::toScalarIfPossible(std::shared_ptr no return NetworkHelper::toScalar(constant); } +std::shared_ptr foldConvert(const Output& node, const element::Type targetPrecision) { + if (is_type(node.get_node_shared_ptr()) && (node.get_element_type() == targetPrecision)) { + return node.get_node_shared_ptr(); + } + + return fold(node, targetPrecision); +} + bool NetworkHelper::checkZeroPoint(const std::shared_ptr& node, const DataPrecision& dataPrecision) { if (!node) { return true; diff --git a/inference-engine/src/low_precision_transformations/src/pull_reshape_through_dequantization.cpp b/inference-engine/src/low_precision_transformations/src/pull_reshape_through_dequantization.cpp index a6dc3fe4e6d..4c4679c8046 100644 --- a/inference-engine/src/low_precision_transformations/src/pull_reshape_through_dequantization.cpp +++ b/inference-engine/src/low_precision_transformations/src/pull_reshape_through_dequantization.cpp @@ -23,13 +23,14 @@ std::shared_ptr moveThroughElementwise(const std::shared_ptr& reshap const auto reshapeValues = reshape->get_input_node_shared_ptr(1); NGRAPH_CHECK(reshapeValues != nullptr, "Reshape constant was not found"); - const auto constantIndex = ngraph::pass::low_precision::NetworkHelper::getConstantInputIndex(elementwise); - NGRAPH_CHECK(constantIndex != -1); - - const auto elementwiseValues = elementwise->get_input_node_shared_ptr(constantIndex); + auto elementwiseValuesConvert = as_type_ptr(elementwise->get_input_node_shared_ptr(1ul)); + auto elementwiseValues = elementwiseValuesConvert == nullptr ? + elementwise->get_input_node_shared_ptr(1ul) : + elementwiseValuesConvert->get_input_node_shared_ptr(0ul); + assert(is_type(elementwiseValues)); const std::shared_ptr newReshape = as_type_ptr(reshape->clone_with_new_inputs({ - elementwise->get_input_node_shared_ptr(constantIndex == 1 ? 0ul : 1ul), + elementwise->get_input_node_shared_ptr(0ul), reshapeValues })); std::shared_ptr newElementwiseValues; @@ -54,10 +55,15 @@ std::shared_ptr moveThroughElementwise(const std::shared_ptr& reshap elementwiseValues->output(0), newReshapeValues->output(0), as_type_ptr(reshape)->get_special_zero()); + assert(is_type(newElementwiseValues)); } else { newElementwiseValues = elementwiseValues; } - const auto newElementwise = elementwise->clone_with_new_inputs({ newReshape, newElementwiseValues }); + const auto newElementwise = elementwise->clone_with_new_inputs({ + newReshape, + elementwiseValuesConvert == nullptr ? + newElementwiseValues : + std::make_shared(newElementwiseValues, elementwiseValuesConvert->get_destination_type()) }); replace_node(reshape, newElementwise); copy_runtime_info({ elementwise, reshape }, { newReshape, newElementwise }); @@ -87,8 +93,12 @@ ngraph::pass::low_precision::PullReshapeThroughDequantization::PullReshapeThroug const std::vector& inputPrecisions) { const auto weights = ngraph::pattern::wrap_type(pattern::type_matches_any(inputPrecisions)); const auto convert = ngraph::pattern::wrap_type({ weights }); - const auto subtractConvert = ngraph::pattern::wrap_type(); - const auto subtract = ngraph::pattern::wrap_type({ convert, subtractConvert }); + + const auto subtractValues = std::make_shared(OutputVector{ + ngraph::pattern::wrap_type(), + ngraph::pattern::wrap_type({ngraph::pattern::wrap_type()}) + }); + const auto subtract = ngraph::pattern::wrap_type({ convert, subtractValues }); const auto subtractOrConvert = std::make_shared(OutputVector{ convert, subtract }); diff --git a/inference-engine/src/low_precision_transformations/src/pull_transpose_through_dequantization.cpp b/inference-engine/src/low_precision_transformations/src/pull_transpose_through_dequantization.cpp index 90f2230848c..a8dd26d26a1 100644 --- a/inference-engine/src/low_precision_transformations/src/pull_transpose_through_dequantization.cpp +++ b/inference-engine/src/low_precision_transformations/src/pull_transpose_through_dequantization.cpp @@ -24,10 +24,12 @@ std::shared_ptr moveThroughElementwise(const std::shared_ptr& transp const auto transposeValues = transpose->get_input_node_shared_ptr(1); NGRAPH_CHECK(transposeValues != nullptr, "transpose constant was not found"); - const auto constantIndex = ngraph::pass::low_precision::NetworkHelper::getConstantInputIndex(elementwise); - NGRAPH_CHECK(constantIndex != -1); + auto elementwiseValuesConvert = as_type_ptr(elementwise->get_input_node_shared_ptr(1ul)); + auto elementwiseValues = elementwiseValuesConvert == nullptr ? + elementwise->get_input_node_shared_ptr(1ul) : + elementwiseValuesConvert->get_input_node_shared_ptr(0ul); + assert(is_type(elementwiseValues)); - auto elementwiseValues = elementwise->get_input_node_shared_ptr(constantIndex); const auto transposeValuesShape = transposeValues->output(0).get_shape(); const auto elementwiseValuesShape = elementwiseValues->output(0).get_shape(); if (elementwiseValuesShape.size() != shape_size(transposeValuesShape)) { @@ -45,7 +47,7 @@ std::shared_ptr moveThroughElementwise(const std::shared_ptr& transp } const std::shared_ptr newTranspose = as_type_ptr(transpose->clone_with_new_inputs({ - elementwise->get_input_node_shared_ptr(constantIndex == 1 ? 0ul : 1ul), + elementwise->get_input_node_shared_ptr(0ul), transposeValues })); const auto newElementwiseValues = ngraph::pass::low_precision::fold( @@ -53,7 +55,11 @@ std::shared_ptr moveThroughElementwise(const std::shared_ptr& transp transposeValues->output(0)); assert(is_type(newElementwiseValues)); - const auto newElementwise = elementwise->clone_with_new_inputs({ newTranspose, newElementwiseValues }); + const auto newElementwise = elementwise->clone_with_new_inputs({ + newTranspose, + elementwiseValuesConvert == nullptr ? + newElementwiseValues : + std::make_shared(newElementwiseValues, elementwiseValuesConvert->get_destination_type()) }); replace_node(transpose, newElementwise); copy_runtime_info({ elementwise, transpose }, { newTranspose, newElementwise }); @@ -85,8 +91,12 @@ ngraph::pass::low_precision::PullTransposeThroughDequantization::PullTransposeTh const std::vector& inputPrecisions) { const auto weights = ngraph::pattern::wrap_type(pattern::type_matches_any(inputPrecisions)); const auto convert = ngraph::pattern::wrap_type({ weights }); - const auto subtractConvert = ngraph::pattern::wrap_type(); - const auto subtract = ngraph::pattern::wrap_type({ convert, subtractConvert }); + + const auto subtractValues = std::make_shared(OutputVector{ + ngraph::pattern::wrap_type(), + ngraph::pattern::wrap_type({ngraph::pattern::wrap_type()}) + }); + const auto subtract = ngraph::pattern::wrap_type({ convert, subtractValues }); const auto subtractOrConvert = std::make_shared(OutputVector{ convert, subtract }); diff --git a/inference-engine/src/low_precision_transformations/src/split.cpp b/inference-engine/src/low_precision_transformations/src/split.cpp index 4dcff39fc5d..c6a1f4b1df1 100644 --- a/inference-engine/src/low_precision_transformations/src/split.cpp +++ b/inference-engine/src/low_precision_transformations/src/split.cpp @@ -91,7 +91,12 @@ bool SplitTransformation::transform(TransformationContext& context, ngraph::patt replacement.push_back(multiply); } - replace_node(split, replacement); + for (size_t i = 0ul; i < newSplit->get_output_size(); ++i) { + for (auto input : split->output(i).get_target_inputs()) { + input.replace_source_output(replacement[i]); + } + } + updateOutputs(context, lastNodes, newSplit); return true; } diff --git a/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp b/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp index 0160830cefb..f79021f93b8 100644 --- a/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp +++ b/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp @@ -101,9 +101,9 @@ bool SubtractMultiplyToMultiplyAddTransformation::transform(TransformationContex std::shared_ptr subtractConstant = fold( fold( - fold(originalSubtractConstant, deqPrecision), + foldConvert(originalSubtractConstant, deqPrecision), std::make_shared(deqPrecision, Shape{}, std::vector{ -1.f })), - fold(dequantization.multiply->get_input_node_shared_ptr(1), deqPrecision)); + foldConvert(dequantization.multiply->get_input_node_shared_ptr(1), deqPrecision)); if (is_type(subtractConstant)) { std::shared_ptr constant = as_type_ptr(subtractConstant); diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index 162c3a530ba..32efc8d09ac 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -164,6 +165,11 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { manager.register_pass(); manager.register_pass(); manager.register_pass(); + + if (useLpt) { + manager.register_pass( + std::vector{ ngraph::element::i8, ngraph::element::u8, ngraph::element::i4, ngraph::element::u4 }); + } manager.register_pass(precisions); auto pass_config = manager.get_pass_config(); diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/convert_subtract_constant_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/convert_subtract_constant_transformation.cpp new file mode 100644 index 00000000000..d908a6c6c9f --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/convert_subtract_constant_transformation.cpp @@ -0,0 +1,333 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "layer_transformation.hpp" + +#include +#include +#include + +#include + +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" +#include "simple_low_precision_transformer.hpp" +#include "lpt_ngraph_functions/fake_quantize_and_convolution_function.hpp" + +using namespace testing; +using namespace ngraph; +using namespace ngraph::pass; + +class ConvertSubtractConstantTransformationTestValues { +public: + class Values { + public: + ngraph::element::Type precisionBeforeDequantization; + ngraph::builder::subgraph::DequantizationOperations dequantizationOnActivations; + ngraph::builder::subgraph::DequantizationOperations dequantizationOnWeights; + ngraph::builder::subgraph::Constant weights; + builder::subgraph::FakeQuantizeOnWeights fakeQuantizeOnWeights; + ngraph::element::Type precisionAfterOperation; + ngraph::builder::subgraph::DequantizationOperations dequantizationAfter; + }; + + ngraph::pass::low_precision::LayerTransformation::Params params; + Values actual; + Values expected; +}; + +typedef std::tuple< + ngraph::Shape, + ConvertSubtractConstantTransformationTestValues> ConvertSubtractConstantTransformationParams; + +class ConvertSubtractConstantTransformation : public LayerTransformation, public testing::WithParamInterface { +public: + void SetUp() override { + const auto inputShape = std::get<0>(GetParam()); + const auto testValues = std::get<1>(GetParam()); + + actualFunction = ngraph::builder::subgraph::FakeQuantizeAndConvolutionFunction::get( + testValues.actual.precisionBeforeDequantization, + inputShape, + {}, + {}, + testValues.actual.dequantizationOnActivations, + testValues.actual.weights, + testValues.actual.fakeQuantizeOnWeights, + {}, + testValues.actual.dequantizationOnWeights, + testValues.actual.dequantizationAfter); + + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(actualFunction); + + referenceFunction = ngraph::builder::subgraph::FakeQuantizeAndConvolutionFunction::get( + testValues.actual.precisionBeforeDequantization, + inputShape, + {}, + {}, + testValues.expected.dequantizationOnActivations, + testValues.expected.weights, + testValues.expected.fakeQuantizeOnWeights, + {}, + testValues.expected.dequantizationOnWeights, + testValues.expected.dequantizationAfter); + } + + + static std::string getTestCaseName(testing::TestParamInfo obj) { + auto inputShape = std::get<0>(obj.param); + ConvertSubtractConstantTransformationTestValues testValues = std::get<1>(obj.param); + + std::ostringstream result; + result << toString(testValues.params) << "_" << + inputShape << "_" << + testValues.actual.precisionBeforeDequantization << "_" << + testValues.actual.dequantizationOnActivations << "_" << "_weights_" << + testValues.actual.weights.outPrecision << "_" << "{ " << + testValues.actual.weights.values[0] << " }_" << + testValues.actual.fakeQuantizeOnWeights << "_" << + testValues.actual.dequantizationOnWeights; + return result.str(); + } +}; + +TEST_P(ConvertSubtractConstantTransformation, CompareFunctions) { + actualFunction->validate_nodes_and_infer_types(); + auto res = compare_functions(referenceFunction, actualFunction, true, true, true); + ASSERT_TRUE(res.first) << res.second; +} + +const std::vector shapes = { + ngraph::Shape({ 1, 3, 72, 48 }), + ngraph::Shape({ 4, 3, 72, 48 }) +}; + +const std::vector testValues = { + // Actual: + // + // Parameter Constant Constant + // |U8 |U8 |I8 + // | | | + // Convert Convert Convert Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Subtract Constant Subtract Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Multiply Multiply + // \FP32 /FP32 + // \ / + // Convolution + // + // Transformed: + // + // Parameter Constant Constant Constant + // |U8 |U8 |I8 |I8 + // | | | | + // Convert Convert Convert Convert + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Subtract Constant Subtract Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Multiply Multiply + // \FP32 /FP32 + // \ / + // Convolution + { + LayerTransformation::createParamsU8I8().setSupportAsymmetricQuantization(true), + // ActualValues + { + ngraph::element::u8, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, + { {0.02f}, element::f32, {}, false } + }, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false }, + { {0.03f}, element::f32, {}, false } + }, + { std::vector{ 2.f }, ngraph::element::i8}, + {}, + ngraph::element::f32, + {} + }, + // ExpectedValues + { + ngraph::element::u8, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, + { {0.02f}, element::f32, {}, false } + }, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::i8, true, {}, { "DISABLED_CONSTANT_FOLDING" } }, + { {0.03f}, element::f32, {}, false } + }, + { std::vector{ 2.f }, ngraph::element::i8}, + {}, + ngraph::element::f32, + {} + } + }, + + // Constant Subtract values are outside INT8 range + // Actual: + // + // Parameter Constant Constant + // |U8 |U8 |I8 + // | | | + // Convert Convert Convert Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Subtract Constant Subtract Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Multiply Multiply + // \FP32 /FP32 + // \ / + // Convolution + // + // Transformed: + // + // Parameter Constant Constant + // |U8 |U8 |I8 + // | | | + // Convert Convert Convert Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Subtract Constant Subtract Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Multiply Multiply + // \FP32 /FP32 + // \ / + // Convolution + { + LayerTransformation::createParamsU8I8().setSupportAsymmetricQuantization(true), + // ActualValues + { + ngraph::element::u8, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, + { {0.02f}, element::f32, {}, false } + }, + { + { ngraph::element::f32, false }, + { {128.f}, element::f32, {}, false }, + { {0.03f}, element::f32, {}, false } + }, + { std::vector{ 2.f }, ngraph::element::i8}, + {}, + ngraph::element::f32, + {} + }, + // ExpectedValues + { + ngraph::element::u8, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, + { {0.02f}, element::f32, {}, false } + }, + { + { ngraph::element::f32, false }, + { {128.f}, element::f32, {}, false }, + { {0.03f}, element::f32, {}, false } + }, + { std::vector{ 2.f }, ngraph::element::i8}, + {}, + ngraph::element::f32, + {} + } + }, + + // Constant Subtract values are close to zero + // Actual: + // + // Parameter Constant Constant + // |U8 |U8 |I8 + // | | | + // Convert Convert Convert Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Subtract Constant Subtract Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Multiply Multiply + // \FP32 /FP32 + // \ / + // Convolution + // + // Transformed: + // + // Parameter Constant + // |U8 |U8 + // | | + // Convert Convert Constant + // \FP32 /FP32 |I8 + // \ / | + // Subtract Constant Convert Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Multiply Multiply + // \FP32 /FP32 + // \ / + // Convolution + { + LayerTransformation::createParamsU8I8().setSupportAsymmetricQuantization(true), + // ActualValues + { + ngraph::element::u8, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, + { {0.02f}, element::f32, {}, false } + }, + { + { ngraph::element::f32, false }, + { {0.000001f}, element::f32, {}, false }, + { {0.03f}, element::f32, {}, false } + }, + { std::vector{ 2.f }, ngraph::element::i8}, + {}, + ngraph::element::f32, + {} + }, + // ExpectedValues + { + ngraph::element::u8, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, + { {0.02f}, element::f32, {}, false } + }, + { + { ngraph::element::f32, false }, + { }, + { {0.03f}, element::f32, {}, false } + }, + { std::vector{ 2.f }, ngraph::element::i8}, + {}, + ngraph::element::f32, + {} + } + }, +}; + +INSTANTIATE_TEST_CASE_P( + smoke_LPT, + ConvertSubtractConstantTransformation, + ::testing::Combine( + ::testing::ValuesIn(shapes), + ::testing::ValuesIn(testValues)), + ConvertSubtractConstantTransformation::getTestCaseName); diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/fold_convert_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/fold_convert_transformation.cpp index f98c78eeeda..68b6e16b9a6 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/fold_convert_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/fold_convert_transformation.cpp @@ -121,6 +121,47 @@ const std::vector testValues = { { {7.f}, ngraph::element::f32, {}, false, 1 }, { 10.f } } + }, + + // Actual: + // + // Constant Parameter + // |U8 |U8 + // | | + // Convert Convert + // \FP32 /FP32 + // \ / + // Subtract Constant + // \FP32 /FP32 + // \ / + // Multiply + // + // Transformed: + // + // Parameter + // |U8 + // | + // Constant Convert + // \FP32 /FP32 + // \ / + // Subtract Constant + // \FP32 /FP32 + // \ / + // Multiply + { + LayerTransformation::createParamsU8I8(), + ngraph::element::f32, + ngraph::Shape{1, 4, 16, 16}, + { + {ngraph::element::f32}, + { {7.f}, ngraph::element::f32, {}, false, 0, ngraph::element::u8, true }, + { 10.f } + }, + { + {ngraph::element::f32}, + { {7.f}, ngraph::element::f32, {}, false, 0 }, + { 10.f } + } } }; diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp index 6fb52b537ba..7ba3252999e 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp @@ -595,7 +595,16 @@ const std::vector testValues = { {}, { {}, - {std::vector(24ul, 127.f), ngraph::element::f32, {24, 1, 1, 1}, false, 1, ngraph::element::i8, false, {"DISABLED_CONSTANT_FOLDING"}}, + { + std::vector(24ul, 127.f), + ngraph::element::f32, + {24, 1, 1, 1}, + false, + 1, + ngraph::element::i8, + false, + {"DEQUANTIZATION", "DISABLED_CONSTANT_FOLDING"} + }, {} }, ngraph::element::f32, diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp index 5a862c059d2..b5e134fdfe0 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp @@ -99,10 +99,12 @@ ngraph::builder::subgraph::DequantizationOperations LayerTransformation::toDequa subtract = dequantization.subtractConstant != nullptr ? ngraph::builder::subgraph::DequantizationOperations::Subtract( dequantization.subtractConstant->cast_vector(), - dequantization.subtractConstant->output(0).get_element_type(), + dequantization.subtract->output(0).get_element_type(), dequantization.subtractConstant->output(0).get_shape(), addDequantizationAttribute, - constantIndex) : + constantIndex, + dequantization.subtractConstant->output(0).get_element_type(), + dequantization.subtractConvert != nullptr) : ngraph::builder::subgraph::DequantizationOperations::Subtract(); } diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/pull_reshape_through_dequantization_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/pull_reshape_through_dequantization_transformation.cpp index cec2abdb330..f00dcc62173 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/pull_reshape_through_dequantization_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/pull_reshape_through_dequantization_transformation.cpp @@ -154,6 +154,7 @@ const std::vector multiplyShapes = { }; const std::vector testValues = { + // Subtract with Constant (no Convert) // Actual: // Constant // |I8 @@ -248,6 +249,103 @@ const std::vector testValues = { ngraph::element::f32, {} } + }, + + // Subtract with Convert + Constant + // Actual: + // Constant Constant + // |I8 |I8 + // | | + // Convert Convert + // |FP32 /FP32 + // | / + // Subtract Constant + // |FP32 /FP32 + // | / + // Multiply Constant + // |FP32 /FP32 + // | / + // Parameter Constant Reshape Constant + // |U8 |U8 |FP32 /FP32 + // | | | / + // Convert Convert Multiply Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Subtract Constant Transpose Constant + // \FP32 /FP32 |FP32 /I64 + // \ / | / + // Multiply Reshape + // \FP32 /FP32 + // \ / + // GroupConvolution + // + // + // Transformed: + // + // Constant + // |I8 + // | + // Parameter Constant Convert Constant + // |U8 |U8 |FP32 /FP32 + // | | | / + // Convert Convert Subtract Constant + // \FP32 /FP32 |FP32 /FP32 + // \ / | / + // Subtract Constant Multiply Constant + // \FP32 /FP32 |FP32 /I64 + // \ / | / + // Multiply Reshape + // \FP32 /FP32 + // \ / + // GroupConvolution Constant + // \FP32 /FP32 + // \ / + // Multiply + // + { + LayerTransformation::createParamsU8I8().setSupportAsymmetricQuantization(true), + // ActualValues + { + ngraph::element::u8, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, + { {0.02f}, element::f32, {}, false } + }, + { std::vector{ 2.f }, ngraph::element::i8, {9, 960}}, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {/* from parameter */}, false, 1ul, element::i8, true }, + { {0.03f}, element::f32, {/* from parameter */}, false } + }, + { {3, 3, 960, 1} }, + { {2}, element::f32, {/* from parameter: multiplyShapes */}, false }, + { {2, 3, 0, 1} }, + { {960, 1, 1, 3, 3} }, + ngraph::element::f32, + {} + }, + // ExpectedValues + { + ngraph::element::u8, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, + { {0.02f}, element::f32, {}, false } + }, + { std::vector{ 2.f }, ngraph::element::i8, {960, 1, 3, 3}}, + { + { ngraph::element::f32, false }, + { {127.f}, element::f32, {/* from parameter */}, false, 1ul, element::i8, true }, + { {0.06f}, element::f32, {/* from parameter */}, false } + }, + {}, + {}, + {}, + {{960, 1, 1, 3, 3}}, + ngraph::element::f32, + {} + } } }; diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_quantize_dequantize.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_quantize_dequantize.cpp index b9497f79f28..b26fe429fae 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_quantize_dequantize.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_quantize_dequantize.cpp @@ -23,9 +23,9 @@ using namespace testing; using namespace ngraph; -template +template std::shared_ptr create_q_dq_function(const Shape& data_shape, float in_low, float in_high, float out_low, float out_high, - const Shape& zero_point_shape, std::vector zero_point_values, + const Shape& zero_point_shape, std::vector zero_point_values, /*const bool zero_point_in_f32,*/ const Shape& scale_shape, std::vector scale_values, size_t levels) { auto data = std::make_shared(element::f32, data_shape); auto input_low = opset1::Constant::create(element::f32, Shape{}, {in_low}); @@ -35,9 +35,13 @@ std::shared_ptr create_q_dq_function(const Shape& data_shape, float in auto fq = std::make_shared(data, input_low, input_high, output_low, output_high, levels); - auto convert1 = std::make_shared(fq, element::from()); + auto convert1 = std::make_shared(fq, element::from()); auto convert2 = std::make_shared(convert1, element::f32); - auto zero_point = std::make_shared(opset1::Constant::create(element::from(), zero_point_shape, zero_point_values), element::f32); + const std::shared_ptr zero_point = element::from() == element::f32 ? + opset1::Constant::create(element::from(), zero_point_shape, zero_point_values) : + std::dynamic_pointer_cast(std::make_shared( + opset1::Constant::create(element::from(), zero_point_shape, zero_point_values), + element::f32)); auto sub = std::make_shared(convert2, zero_point); auto scale = opset1::Constant::create(element::f32, scale_shape, scale_values); auto mul = std::make_shared(sub, scale); @@ -45,19 +49,21 @@ std::shared_ptr create_q_dq_function(const Shape& data_shape, float in return std::make_shared(NodeVector{mul}, ParameterVector{data}); } -template +template void positive_test(const Shape& data_shape, float in_low, float in_high, float out_low, float out_high, const Shape& zero_point_shape, std::vector zero_point_values, const Shape& scale_shape, std::vector scale_values, size_t levels) { std::shared_ptr f(nullptr), f_ref(nullptr); { - f = create_q_dq_function(data_shape, in_low, in_high, out_low, out_high, + f = create_q_dq_function(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); + pass::Manager m; m.register_pass(); m.register_pass(); m.register_pass(); m.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); } @@ -77,7 +83,7 @@ void positive_test(const Shape& data_shape, float in_low, float in_high, float o ASSERT_TRUE(res.first) << res.second; } -TEST(TransformationTests, ConvertQuantizeDequantizeINT8) { +TEST(TransformationTests, ConvertQuantizeDequantizeINT8WithINT8ZeroPoint) { std::shared_ptr f(nullptr), f_ref(nullptr); Shape data_shape{3, 1, 2}; float in_low = 0; @@ -90,11 +96,28 @@ TEST(TransformationTests, ConvertQuantizeDequantizeINT8) { std::vector scale_values{3}; size_t levels = 256; - positive_test(data_shape, in_low, in_high, out_low, out_high, + positive_test(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); } -TEST(TransformationTests, ConvertQuantizeDequantizeUINT8) { +TEST(TransformationTests, ConvertQuantizeDequantizeINT8WithFP32ZeroPoint) { + std::shared_ptr f(nullptr), f_ref(nullptr); + Shape data_shape{ 3, 1, 2 }; + float in_low = 0; + float in_high = 5; + float out_low = -128; + float out_high = 127; + Shape zero_point_shape{}; + std::vector zero_point_values{ 2 }; + Shape scale_shape{}; + std::vector scale_values{ 3 }; + size_t levels = 256; + + positive_test(data_shape, in_low, in_high, out_low, out_high, + zero_point_shape, zero_point_values, scale_shape, scale_values, levels); +} + +TEST(TransformationTests, ConvertQuantizeDequantizeUINT8WithUINT8ZeroPoint) { std::shared_ptr f(nullptr), f_ref(nullptr); Shape data_shape{3, 1, 2}; float in_low = 0; @@ -107,17 +130,34 @@ TEST(TransformationTests, ConvertQuantizeDequantizeUINT8) { std::vector scale_values{3}; size_t levels = 256; - positive_test(data_shape, in_low, in_high, out_low, out_high, + positive_test(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); } -template +TEST(TransformationTests, ConvertQuantizeDequantizeUINT8WithFP32ZeroPoint) { + std::shared_ptr f(nullptr), f_ref(nullptr); + Shape data_shape{ 3, 1, 2 }; + float in_low = 0; + float in_high = 5; + float out_low = 0; + float out_high = 255; + Shape zero_point_shape{}; + std::vector zero_point_values{ 2 }; + Shape scale_shape{}; + std::vector scale_values{ 3 }; + size_t levels = 256; + + positive_test(data_shape, in_low, in_high, out_low, out_high, + zero_point_shape, zero_point_values, scale_shape, scale_values, levels); +} + +template void negative_test(const Shape& data_shape, float in_low, float in_high, float out_low, float out_high, const Shape& zero_point_shape, std::vector zero_point_values, const Shape& scale_shape, std::vector scale_values, size_t levels) { std::shared_ptr f(nullptr), f_ref(nullptr); { - f = create_q_dq_function(data_shape, in_low, in_high, out_low, out_high, + f = create_q_dq_function(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); pass::Manager m; m.register_pass(); @@ -128,14 +168,14 @@ void negative_test(const Shape& data_shape, float in_low, float in_high, float o { // negative test so the transformation does not fire and reference is the same graph as original - f_ref = create_q_dq_function(data_shape, in_low, in_high, out_low, out_high, + f_ref = create_q_dq_function(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); } auto res = compare_functions(f, f_ref); ASSERT_TRUE(res.first) << res.second; } -TEST(TransformationTests, ConvertQuantizeDequantizeZeroPointNotBroadcastable) { +TEST(TransformationTests, ConvertQuantizeDequantizeZeroPointNotBroadcastableWithINT8ZeroPoint) { std::shared_ptr f(nullptr), f_ref(nullptr); Shape data_shape{3, 1, 2}; float in_low = 0; @@ -148,11 +188,28 @@ TEST(TransformationTests, ConvertQuantizeDequantizeZeroPointNotBroadcastable) { std::vector scale_values{3}; size_t levels = 256; - negative_test(data_shape, in_low, in_high, out_low, out_high, + negative_test(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); } -TEST(TransformationTests, ConvertQuantizeDequantizeScaleNotBroadcastable) { +TEST(TransformationTests, ConvertQuantizeDequantizeZeroPointNotBroadcastableWithFP32ZeroPoint) { + std::shared_ptr f(nullptr), f_ref(nullptr); + Shape data_shape{ 3, 1, 2 }; + float in_low = 0; + float in_high = 5; + float out_low = -128; + float out_high = 127; + Shape zero_point_shape{ 1, 1, 1, 1 }; + std::vector zero_point_values{ 2 }; + Shape scale_shape{ 1 }; + std::vector scale_values{ 3 }; + size_t levels = 256; + + negative_test(data_shape, in_low, in_high, out_low, out_high, + zero_point_shape, zero_point_values, scale_shape, scale_values, levels); +} + +TEST(TransformationTests, ConvertQuantizeDequantizeScaleNotBroadcastableWithINT8ZeroPoint) { std::shared_ptr f(nullptr), f_ref(nullptr); Shape data_shape{3, 1, 2}; float in_low = 0; @@ -165,11 +222,28 @@ TEST(TransformationTests, ConvertQuantizeDequantizeScaleNotBroadcastable) { std::vector scale_values{3}; size_t levels = 256; - negative_test(data_shape, in_low, in_high, out_low, out_high, + negative_test(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); } -TEST(TransformationTests, ConvertQuantizeDequantizeInvalidLevels) { +TEST(TransformationTests, ConvertQuantizeDequantizeScaleNotBroadcastableWithFP32ZeroPoint) { + std::shared_ptr f(nullptr), f_ref(nullptr); + Shape data_shape{ 3, 1, 2 }; + float in_low = 0; + float in_high = 5; + float out_low = -128; + float out_high = 127; + Shape zero_point_shape{}; + std::vector zero_point_values{ 2 }; + Shape scale_shape{ 1, 1, 1, 1 }; + std::vector scale_values{ 3 }; + size_t levels = 256; + + negative_test(data_shape, in_low, in_high, out_low, out_high, + zero_point_shape, zero_point_values, scale_shape, scale_values, levels); +} + +TEST(TransformationTests, ConvertQuantizeDequantizeInvalidLevelsWithINT8ZeroPoint) { std::shared_ptr f(nullptr), f_ref(nullptr); Shape data_shape{3, 1, 2}; float in_low = 0; @@ -182,11 +256,28 @@ TEST(TransformationTests, ConvertQuantizeDequantizeInvalidLevels) { std::vector scale_values{3}; size_t levels = 127; - negative_test(data_shape, in_low, in_high, out_low, out_high, + negative_test(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); } -TEST(TransformationTests, ConvertQuantizeDequantizeInvalidOutLowOutHigh) { +TEST(TransformationTests, ConvertQuantizeDequantizeInvalidLevelsWithFP32ZeroPoint) { + std::shared_ptr f(nullptr), f_ref(nullptr); + Shape data_shape{ 3, 1, 2 }; + float in_low = 0; + float in_high = 5; + float out_low = -128; + float out_high = 127; + Shape zero_point_shape{}; + std::vector zero_point_values{ 2 }; + Shape scale_shape{}; + std::vector scale_values{ 3 }; + size_t levels = 127; + + negative_test(data_shape, in_low, in_high, out_low, out_high, + zero_point_shape, zero_point_values, scale_shape, scale_values, levels); +} + +TEST(TransformationTests, ConvertQuantizeDequantizeInvalidOutLowOutHighWithUINT8ZeroPoint) { std::shared_ptr f(nullptr), f_ref(nullptr); Shape data_shape{3, 1, 2}; float in_low = 0; @@ -200,6 +291,24 @@ TEST(TransformationTests, ConvertQuantizeDequantizeInvalidOutLowOutHigh) { std::vector scale_values{3}; size_t levels = 256; - negative_test(data_shape, in_low, in_high, out_low, out_high, + negative_test(data_shape, in_low, in_high, out_low, out_high, zero_point_shape, zero_point_values, scale_shape, scale_values, levels); } + +TEST(TransformationTests, ConvertQuantizeDequantizeInvalidOutLowOutHighWithFP32ZeroPoint) { + std::shared_ptr f(nullptr), f_ref(nullptr); + Shape data_shape{ 3, 1, 2 }; + float in_low = 0; + float in_high = 5; + // (-128, 127) are invalid for uin8_t data type + float out_low = -128; + float out_high = 127; + Shape zero_point_shape{}; + std::vector zero_point_values{ 2 }; + Shape scale_shape{}; + std::vector scale_values{ 3 }; + size_t levels = 256; + + negative_test(data_shape, in_low, in_high, out_low, out_high, + zero_point_shape, zero_point_values, scale_shape, scale_values, levels); +} diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp index 0342e4e5cd6..22c57ab6049 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp @@ -73,11 +73,18 @@ std::shared_ptr makeDequantization( if (((dequantizationOperations.subtract.outPrecision == element::undefined) || (dequantizationOperations.subtract.outPrecision == parent.get_element_type())) && - ((dequantizationOperations.subtract.constantPrecision == element::undefined) || - (dequantizationOperations.subtract.constantPrecision == parent.get_element_type()))) { - subtract = dequantizationOperations.subtract.addDequantizationAttribute ? - std::make_shared(parent, subtractConst) : - std::make_shared(parent, subtractConst); + (((dequantizationOperations.subtract.constantPrecision == element::undefined) || + (dequantizationOperations.subtract.constantPrecision == parent.get_element_type())) || + dequantizationOperations.subtract.addConvert)) { + if (dequantizationOperations.subtract.constantIndex == 1ul) { + subtract = dequantizationOperations.subtract.addDequantizationAttribute ? + std::make_shared(parent, subtractConst) : + std::make_shared(parent, subtractConst); + } else { + subtract = dequantizationOperations.subtract.addDequantizationAttribute ? + std::make_shared(subtractConst, parent) : + std::make_shared(subtractConst, parent); + } } else { // TODO: use templates if (dequantizationOperations.subtract.addDequantizationAttribute) { From 1353ed1f85b2128ae1a224e0c02809e95f16ed5c Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 15 May 2021 11:42:09 +0300 Subject: [PATCH 81/99] Support old TBBs in cmake (#5638) * Support old TBBs * Don't reset environment * Removed useless NO_CMAKE_FIND_ROOT_PATH * Fixed build with old TBB for Windows * Fixed ngraph code style --- .../download/dependency_solver.cmake | 6 +++--- inference-engine/CMakeLists.txt | 1 + inference-engine/cmake/dependencies.cmake | 2 ++ .../cmake/templates/InferenceEngineConfig.cmake.in | 4 ++-- .../src/vpu/graph_transformer/CMakeLists.txt | 7 +++++++ ngraph/python/src/pyngraph/axis_set.cpp | 12 ++++-------- ngraph/python/src/pyngraph/axis_vector.cpp | 9 +++------ ngraph/python/src/pyngraph/shape.cpp | 9 +++------ ngraph/python/src/pyngraph/strides.cpp | 9 +++------ 9 files changed, 28 insertions(+), 31 deletions(-) diff --git a/cmake/developer_package/download/dependency_solver.cmake b/cmake/developer_package/download/dependency_solver.cmake index 2f2ab192d3e..9038f610035 100644 --- a/cmake/developer_package/download/dependency_solver.cmake +++ b/cmake/developer_package/download/dependency_solver.cmake @@ -176,9 +176,9 @@ function(reset_deps_cache) foreach(var_name IN LISTS ARGN) unset(${var_name} CACHE) endforeach() - foreach(var_name IN LISTS ARGN) - unset(ENV{${var_name}}) - endforeach() + # foreach(var_name IN LISTS ARGN) + # unset(ENV{${var_name}}) + # endforeach() endif() endfunction() diff --git a/inference-engine/CMakeLists.txt b/inference-engine/CMakeLists.txt index 57c91518064..1066dcaf35d 100644 --- a/inference-engine/CMakeLists.txt +++ b/inference-engine/CMakeLists.txt @@ -122,6 +122,7 @@ if(SPEECH_LIBS_AND_DEMOS) install(DIRECTORY ${TEMP}/deployment_tools ${TEMP}/data_processing DESTINATION . + USE_SOURCE_PERMISSIONS COMPONENT speech_demo_files) endif() diff --git a/inference-engine/cmake/dependencies.cmake b/inference-engine/cmake/dependencies.cmake index 85adfd45089..0a0770f06ec 100644 --- a/inference-engine/cmake/dependencies.cmake +++ b/inference-engine/cmake/dependencies.cmake @@ -103,10 +103,12 @@ if (THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") RESOLVE_DEPENDENCY(TBB ARCHIVE_LIN "tbb2020_20200415_lin_strip.tgz" TARGET_PATH "${TEMP}/tbb" + ENVIRONMENT "TBBROOT" SHA256 "95b2f3b0b70c7376a0c7de351a355c2c514b42c4966e77e3e34271a599501008") RESOLVE_DEPENDENCY(TBBBIND_2_4 ARCHIVE_LIN "tbbbind_2_4_static_lin_v2.tgz" TARGET_PATH "${TEMP}/tbbbind_2_4" + ENVIRONMENT "TBBBIND_2_4_ROOT" SHA256 "6dc926258c6cd3cba0f5c2cc672fd2ad599a1650fe95ab11122e8f361a726cb6") elseif(LINUX AND AARCH64) RESOLVE_DEPENDENCY(TBB diff --git a/inference-engine/cmake/templates/InferenceEngineConfig.cmake.in b/inference-engine/cmake/templates/InferenceEngineConfig.cmake.in index 06ef59767d5..73b6b966096 100644 --- a/inference-engine/cmake/templates/InferenceEngineConfig.cmake.in +++ b/inference-engine/cmake/templates/InferenceEngineConfig.cmake.in @@ -54,13 +54,13 @@ endmacro() set(IE_PACKAGE_PREFIX_DIR "${PACKAGE_PREFIX_DIR}") set(THREADING "@THREADING@") -if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") +if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO" AND NOT TBB_FOUND) set_and_check(_tbb_dir "@PACKAGE_IE_TBB_DIR@") _ie_find_dependency(TBB COMPONENTS tbb tbbmalloc CONFIG PATHS ${TBBROOT}/cmake - ${_tbb_dir} + ${_tbb_dir} NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH) endif() diff --git a/inference-engine/src/vpu/graph_transformer/CMakeLists.txt b/inference-engine/src/vpu/graph_transformer/CMakeLists.txt index 4eb0cfcaeee..872f0bef2e3 100644 --- a/inference-engine/src/vpu/graph_transformer/CMakeLists.txt +++ b/inference-engine/src/vpu/graph_transformer/CMakeLists.txt @@ -9,6 +9,13 @@ function(add_graph_transformer_target TARGET_NAME STATIC_IE) set_ie_threading_interface_for(${TARGET_NAME}) + # To avoid further TBB find_package action in next call of this function. Some version of TBB + # has an issue with cmake config which lead to fail in case of multiple call of find_package + # from one cmake script file. + set("TBB_FOUND" ${TBB_FOUND} PARENT_SCOPE) + set("TBB_IMPORTED_TARGETS" ${TBB_IMPORTED_TARGETS} PARENT_SCOPE) + set("TBB_VERSION" ${TBB_VERSION} PARENT_SCOPE) + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # TODO: enable some day and fix all warnings # target_compile_options(${TARGET_NAME} PRIVATE "-Wall") diff --git a/ngraph/python/src/pyngraph/axis_set.cpp b/ngraph/python/src/pyngraph/axis_set.cpp index 7fd725ede35..bfa92ff6a0f 100644 --- a/ngraph/python/src/pyngraph/axis_set.cpp +++ b/ngraph/python/src/pyngraph/axis_set.cpp @@ -18,14 +18,10 @@ void regclass_pyngraph_AxisSet(py::module m) { py::class_> axis_set(m, "AxisSet"); axis_set.doc() = "ngraph.impl.AxisSet wraps ngraph::AxisSet"; - axis_set.def(py::init&>(), - py::arg("axes")); - axis_set.def(py::init&>(), - py::arg("axes")); - axis_set.def(py::init&>(), - py::arg("axes")); - axis_set.def(py::init(), - py::arg("axes")); + axis_set.def(py::init&>(), py::arg("axes")); + axis_set.def(py::init&>(), py::arg("axes")); + axis_set.def(py::init&>(), py::arg("axes")); + axis_set.def(py::init(), py::arg("axes")); axis_set.def("__len__", [](const ngraph::AxisSet& v) { return v.size(); }); diff --git a/ngraph/python/src/pyngraph/axis_vector.cpp b/ngraph/python/src/pyngraph/axis_vector.cpp index 836e43f4ae3..f8c8feea25c 100644 --- a/ngraph/python/src/pyngraph/axis_vector.cpp +++ b/ngraph/python/src/pyngraph/axis_vector.cpp @@ -15,10 +15,7 @@ void regclass_pyngraph_AxisVector(py::module m) py::class_> axis_vector(m, "AxisVector"); axis_vector.doc() = "ngraph.impl.AxisVector wraps ngraph::AxisVector"; - axis_vector.def(py::init&>(), - py::arg("axes")); - axis_vector.def(py::init&>(), - py::arg("axes")); - axis_vector.def(py::init(), - py::arg("axes")); + axis_vector.def(py::init&>(), py::arg("axes")); + axis_vector.def(py::init&>(), py::arg("axes")); + axis_vector.def(py::init(), py::arg("axes")); } diff --git a/ngraph/python/src/pyngraph/shape.cpp b/ngraph/python/src/pyngraph/shape.cpp index 9702387294e..0d383d4a348 100644 --- a/ngraph/python/src/pyngraph/shape.cpp +++ b/ngraph/python/src/pyngraph/shape.cpp @@ -18,12 +18,9 @@ void regclass_pyngraph_Shape(py::module m) { py::class_> shape(m, "Shape"); shape.doc() = "ngraph.impl.Shape wraps ngraph::Shape"; - shape.def(py::init&>(), - py::arg("axis_lengths")); - shape.def(py::init&>(), - py::arg("axis_lengths")); - shape.def(py::init(), - py::arg("axis_lengths")); + shape.def(py::init&>(), py::arg("axis_lengths")); + shape.def(py::init&>(), py::arg("axis_lengths")); + shape.def(py::init(), py::arg("axis_lengths")); shape.def("__len__", [](const ngraph::Shape& v) { return v.size(); }); shape.def("__getitem__", [](const ngraph::Shape& v, int key) { return v[key]; }); diff --git a/ngraph/python/src/pyngraph/strides.cpp b/ngraph/python/src/pyngraph/strides.cpp index a33f1a19374..ed89e6c414a 100644 --- a/ngraph/python/src/pyngraph/strides.cpp +++ b/ngraph/python/src/pyngraph/strides.cpp @@ -18,12 +18,9 @@ void regclass_pyngraph_Strides(py::module m) { py::class_> strides(m, "Strides"); strides.doc() = "ngraph.impl.Strides wraps ngraph::Strides"; - strides.def(py::init&>(), - py::arg("axis_strides")); - strides.def(py::init&>(), - py::arg("axis_strides")); - strides.def(py::init(), - py::arg("axis_strides")); + strides.def(py::init&>(), py::arg("axis_strides")); + strides.def(py::init&>(), py::arg("axis_strides")); + strides.def(py::init(), py::arg("axis_strides")); strides.def("__str__", [](const ngraph::Strides& self) -> std::string { std::stringstream stringstream; From 4dd31d079817df408ff035ed786e1024ff6b0eda Mon Sep 17 00:00:00 2001 From: Szymon Durawa Date: Mon, 17 May 2021 05:58:28 +0200 Subject: [PATCH 82/99] Ref implementation transposed convolution visitor test (#5474) * Add visitor test for convolution_backprop. * Add test to CMakeLists, corrected input shapes. * Add checking attributes count. * Extend test for all autoPad types. --- ngraph/test/CMakeLists.txt | 1 + .../test/visitors/op/convolution_backprop.cpp | 86 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 ngraph/test/visitors/op/convolution_backprop.cpp diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 6848436253f..739bc1b498f 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -215,6 +215,7 @@ set(SRC visitors/op/bucketize.cpp visitors/op/constant.cpp visitors/op/convert.cpp + visitors/op/convolution_backprop.cpp visitors/op/cum_sum.cpp visitors/op/deformable_psroi_pooling.cpp visitors/op/detection_output.cpp diff --git a/ngraph/test/visitors/op/convolution_backprop.cpp b/ngraph/test/visitors/op/convolution_backprop.cpp new file mode 100644 index 00000000000..19291bc2b17 --- /dev/null +++ b/ngraph/test/visitors/op/convolution_backprop.cpp @@ -0,0 +1,86 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#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, convolution_backprop_op) +{ + NodeBuilder::get_ops().register_factory(); + auto data = make_shared(element::f32, Shape{1, 16, 124, 124}); + auto filters = make_shared(element::f32, Shape{16, 2, 3, 3}); + auto strides = Strides{1, 1}; + auto pads_begin = CoordinateDiff{1, 2}; + auto pads_end = CoordinateDiff{1, 2}; + auto dilations = Strides{1, 1}; + auto convolution = make_shared( + data, filters, strides, pads_begin, pads_end, dilations, op::PadType::VALID); + NodeBuilder builder(convolution); + auto g_convolution = as_type_ptr(builder.create()); + + // attribute count + const auto expected_attr_count = 6; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); + + EXPECT_EQ(g_convolution->get_strides(), convolution->get_strides()); + EXPECT_EQ(g_convolution->get_pads_begin(), convolution->get_pads_begin()); + EXPECT_EQ(g_convolution->get_pads_end(), convolution->get_pads_end()); + EXPECT_EQ(g_convolution->get_dilations(), convolution->get_dilations()); + EXPECT_EQ(g_convolution->get_auto_pad(), convolution->get_auto_pad()); +} + +TEST(attributes, convolution_backprop_output_shape_output_padding) +{ + NodeBuilder::get_ops().register_factory(); + const auto data = make_shared(element::f32, Shape{1, 16, 124, 124}); + const auto filter = make_shared(element::f32, Shape{16, 2, 3, 3}); + const auto output_shape = make_shared(element::i32, Shape{1}); + + const auto strides = Strides{2, 1}; + const auto pads_begin = CoordinateDiff{3, 4}; + const auto pads_end = CoordinateDiff{4, 6}; + const auto dilations = Strides{3, 1}; + const auto output_padding = CoordinateDiff{3, 4}; + + const std::initializer_list allPadTypes = {op::PadType::EXPLICIT, op::PadType::SAME_UPPER, op::PadType::SAME_LOWER, op::PadType::VALID, op::PadType::AUTO, op::PadType::NOTSET}; + + for (auto padType : allPadTypes) + { + const auto convolution = make_shared(data, + filter, + output_shape, + strides, + pads_begin, + pads_end, + dilations, + padType, + output_padding); + NodeBuilder builder(convolution); + const auto g_convolution = as_type_ptr(builder.create()); + + // attribute count + const auto expected_attr_count = 6; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); + + EXPECT_EQ(g_convolution->get_strides(), convolution->get_strides()); + EXPECT_EQ(g_convolution->get_pads_begin(), convolution->get_pads_begin()); + EXPECT_EQ(g_convolution->get_pads_end(), convolution->get_pads_end()); + EXPECT_EQ(g_convolution->get_dilations(), convolution->get_dilations()); + EXPECT_EQ(g_convolution->get_auto_pad(), convolution->get_auto_pad()); + EXPECT_EQ(g_convolution->get_output_padding(), convolution->get_output_padding()); + } +} From c3b41811838cd9b077b7b971c7928c0b81a9cf8e Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Mon, 17 May 2021 08:11:17 +0300 Subject: [PATCH 83/99] [nG] Add upgrading transformation Gather-1 -> Gather-7 (#5571) * add upgrading gather1 -> gather7 transformation * added G1->G7 to common_optimizations list but by default in turned off * fixed a couple of typos in comments * corrected validation error messages for GatherBase * removed redundant comments * clang format fix * coNverts v1::Gather into v7::Gather * added explicit batch_dims = 0, corrected axis bound check for dynamic data_rank --- .../convert_gather_v1_to_gather_v7.hpp | 27 ++++++++++ .../convert_gather_v7_to_gather_v1.hpp | 2 +- .../common_optimizations.cpp | 3 +- .../convert_gather_v1_to_gather_v7.cpp | 37 +++++++++++++ .../convert_gather_v1_to_gather_v7_test.cpp | 52 +++++++++++++++++++ ngraph/core/include/ngraph/op/gather.hpp | 3 +- ngraph/core/src/op/util/gather_base.cpp | 33 ++++++------ ngraph/test/type_prop/gather.cpp | 23 ++++++-- 8 files changed, 158 insertions(+), 22 deletions(-) create mode 100644 inference-engine/src/transformations/include/transformations/op_conversions/convert_gather_v1_to_gather_v7.hpp create mode 100644 inference-engine/src/transformations/src/transformations/op_conversions/convert_gather_v1_to_gather_v7.cpp create mode 100644 inference-engine/tests/functional/inference_engine/transformations/convert_gather_v1_to_gather_v7_test.cpp diff --git a/inference-engine/src/transformations/include/transformations/op_conversions/convert_gather_v1_to_gather_v7.hpp b/inference-engine/src/transformations/include/transformations/op_conversions/convert_gather_v1_to_gather_v7.hpp new file mode 100644 index 00000000000..c7dd7c30b55 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/op_conversions/convert_gather_v1_to_gather_v7.hpp @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include + +namespace ngraph { +namespace pass { + +class TRANSFORMATIONS_API ConvertGather1ToGather7; + +} // namespace pass +} // namespace ngraph + +/** + * @ingroup ie_transformation_common_api + * @brief ConvertGather1ToGather7 converts v1::Gather into v7::Gather. + */ +class ngraph::pass::ConvertGather1ToGather7 : public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + ConvertGather1ToGather7(); +}; diff --git a/inference-engine/src/transformations/include/transformations/op_conversions/convert_gather_v7_to_gather_v1.hpp b/inference-engine/src/transformations/include/transformations/op_conversions/convert_gather_v7_to_gather_v1.hpp index 757d20390d3..af8e29807ad 100644 --- a/inference-engine/src/transformations/include/transformations/op_conversions/convert_gather_v7_to_gather_v1.hpp +++ b/inference-engine/src/transformations/include/transformations/op_conversions/convert_gather_v7_to_gather_v1.hpp @@ -18,7 +18,7 @@ class TRANSFORMATIONS_API ConvertGather7ToGather1; /** * @ingroup ie_transformation_common_api - * @brief ConvertGather7ToGather1 covert v7::Gather into v1::Gather. + * @brief ConvertGather7ToGather1 converts v7::Gather into v1::Gather. */ class ngraph::pass::ConvertGather7ToGather1 : public ngraph::pass::MatcherPass { public: diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp index 1e281888b98..b8aaa7d09ef 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp @@ -45,6 +45,7 @@ #include "transformations/op_conversions/convert_pad_to_group_conv.hpp" #include "transformations/op_conversions/convert_divide.hpp" #include "transformations/op_conversions/convert_gather_v7_to_gather_v1.hpp" +#include "transformations/op_conversions/convert_gather_v1_to_gather_v7.hpp" #include "transformations/op_conversions/convert_mod.hpp" #include "transformations/op_conversions/convert_minimum_to_power_and_max.hpp" #include "transformations/op_conversions/convert_negative.hpp" @@ -161,8 +162,8 @@ bool ngraph::pass::CommonOptimizations::run_on_function(std::shared_ptrset_name("ngraph::pass::ConvFusions"); manager.register_pass(); - // need to convert to Gather-1 until plugins do not support Gather-7 manager.register_pass(); + manager.register_pass(); auto fq_fusions = manager.register_pass(); fq_fusions->add_matcher(); diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/convert_gather_v1_to_gather_v7.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/convert_gather_v1_to_gather_v7.cpp new file mode 100644 index 00000000000..7037c880eb5 --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/op_conversions/convert_gather_v1_to_gather_v7.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/op_conversions/convert_gather_v1_to_gather_v7.hpp" +#include +#include +#include +#include +#include "itt.hpp" + +NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertGather1ToGather7, "ConvertGather1ToGather7", 0); + +ngraph::pass::ConvertGather1ToGather7::ConvertGather1ToGather7() { + MATCHER_SCOPE(ConvertGather1ToGather7); + + auto gather_v1 = pattern::wrap_type(); + + ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) { + auto gather_v1_node = m.get_match_root(); + if (!gather_v1_node) + return false; + + auto data_input = gather_v1_node->input_value(0); + auto indices_input = gather_v1_node->input_value(1); + auto axis_input = gather_v1_node->input_value(2); + + auto gather_v7 = std::make_shared(data_input, indices_input, axis_input, 0); + gather_v7->set_friendly_name(gather_v1_node->get_friendly_name()); + ngraph::copy_runtime_info(gather_v1_node, gather_v7); + ngraph::replace_node(gather_v1_node, gather_v7); + return true; + }; + + auto m = std::make_shared(gather_v1, matcher_name); + register_matcher(m, callback); +} diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_gather_v1_to_gather_v7_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_gather_v1_to_gather_v7_test.cpp new file mode 100644 index 00000000000..db39785cc4f --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_gather_v1_to_gather_v7_test.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; + +TEST(TransformationTests, ConvertGather1toGather7) { + std::shared_ptr f(nullptr), f_ref(nullptr); + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3}); + auto indices = std::make_shared(ngraph::element::i32, ngraph::Shape{2, 2}); + auto axis = ngraph::opset1::Constant::create(ngraph::element::i32, ngraph::Shape{1}, {0}); + + auto gather_v1 = std::make_shared(data, indices, axis); + + f = std::make_shared(ngraph::NodeVector{gather_v1}, ngraph::ParameterVector{data, indices}); + + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3}); + auto indices = std::make_shared(ngraph::element::i32, ngraph::Shape{2, 2}); + auto axis = ngraph::opset1::Constant::create(ngraph::element::i32, ngraph::Shape{1}, {0}); + + auto gather_v7 = std::make_shared(data, indices, axis, 0); + + f_ref = std::make_shared(ngraph::NodeVector{gather_v7}, ngraph::ParameterVector{data, indices}); + } + + auto res = compare_functions(f, f_ref); + ASSERT_TRUE(res.first) << res.second; +} diff --git a/ngraph/core/include/ngraph/op/gather.hpp b/ngraph/core/include/ngraph/op/gather.hpp index 61463363b05..9293521a7d0 100644 --- a/ngraph/core/include/ngraph/op/gather.hpp +++ b/ngraph/core/include/ngraph/op/gather.hpp @@ -46,7 +46,8 @@ namespace ngraph /// \param data The tensor from which slices are gathered /// \param indices Tensor with indexes to gather /// \param axis The tensor is a dimension index to gather data from - /// \param batch_dims The number of batch dimension in data and indices tensors + /// \param batch_dims The number of batch dimension in data and indices tensors. + /// If batch_dims = 0 Gather v7 is identical to Gather v1. Gather(const Output& data, const Output& indices, const Output& axis, diff --git a/ngraph/core/src/op/util/gather_base.cpp b/ngraph/core/src/op/util/gather_base.cpp index 9da96d4849c..a58ab3e3851 100644 --- a/ngraph/core/src/op/util/gather_base.cpp +++ b/ngraph/core/src/op/util/gather_base.cpp @@ -64,25 +64,26 @@ void op::util::GatherBase::validate_and_infer_types() if (axis_is_set) { - int64_t axis = get_axis(); + int64_t axis = get_axis(); // will be normalized to positive if data_rank is static // batch_dims, axis both can be positive by default or after normalization if data_rank & - // indices_rank are static. If at least one of them is negative we cannot check their - // consistency. - NODE_VALIDATION_CHECK(this, - batch_dims <= axis || batch_dims < 0 || axis < 0, - "The batch_dims <= axis. But instead got: batch_dims = ", - batch_dims, - ", axis = ", - axis); + // indices_rank are static. + // If at least one of them is negative we cannot check their consistency. + NODE_VALIDATION_CHECK( + this, + batch_dims <= axis || batch_dims < 0 || axis < 0, + "After normalization batch_dims must be <= axis. But instead got: batch_dims = ", + batch_dims, + ", axis = ", + axis); - NODE_VALIDATION_CHECK(this, - (axis >= 0 && axis < data_rank.get_length()) || - data_rank.is_dynamic(), - "The axis must be >= 0 and < data_rank. But instead got axis = ", - axis, - " data_rank = ", - data_rank.get_interval()); + NODE_VALIDATION_CHECK( + this, + data_rank.is_dynamic() || (axis >= 0 && axis < data_rank.get_length()), + "Normalized axis must be >= 0 and < data_rank. But instead got axis = ", + axis, + " data_rank = ", + data_rank.get_interval()); } if (indices_rank.is_static() && batch_dims >= 0) diff --git a/ngraph/test/type_prop/gather.cpp b/ngraph/test/type_prop/gather.cpp index a76b24ef57e..70bfc8530ee 100644 --- a/ngraph/test/type_prop/gather.cpp +++ b/ngraph/test/type_prop/gather.cpp @@ -111,7 +111,7 @@ TEST(type_prop, gather_v1_axis_out_of_input_rank) catch (const NodeValidationFailure& error) { EXPECT_HAS_SUBSTRING(error.what(), - std::string("The axis must be >= 0 and < data_rank. But instead got axis")); + std::string("Normalized axis must be >= 0 and < data_rank. But instead got axis")); } catch (...) { @@ -266,6 +266,23 @@ TEST(type_prop, gather_7_dynamic_rank) ASSERT_EQ(G->get_output_partial_shape(0), out_shape); } +TEST(type_prop, gather_7_axis_boundcheck_for_dynamic_data_rank) +{ + PartialShape data_shape = PartialShape::dynamic(); + PartialShape indices_shape{7, 3, 8}; + PartialShape out_shape = PartialShape::dynamic(); + int64_t axis = 3; + int64_t batch_dims = 2; + + auto D = make_shared(element::f32, data_shape); + auto I = make_shared(element::i64, indices_shape); + auto A = make_shared(element::i64, Shape{1}, vector{axis}); + auto G = make_shared(D, I, A, batch_dims); + + ASSERT_EQ(G->get_element_type(), element::f32); + ASSERT_EQ(G->get_output_partial_shape(0), out_shape); +} + TEST(type_prop, gather_7_dynamic_rank_negative_batch_dims) { PartialShape data_shape{Dimension(1, 7), Dimension(1, 3), 200, 400}; @@ -358,7 +375,7 @@ TEST(type_prop, gather_7_axis_out_of_input_rank) catch (const NodeValidationFailure& error) { EXPECT_HAS_SUBSTRING( - error.what(), std::string("The axis must be >= 0 and < data_rank. But instead got")); + error.what(), std::string("Normalized axis must be >= 0 and < data_rank. But instead got")); } catch (...) { @@ -416,7 +433,7 @@ TEST(type_prop, gather_7_batch_dims_less_check) { EXPECT_HAS_SUBSTRING( error.what(), - std::string("batch_dims <= axis. But instead got: batch_dims =")); + std::string("After normalization batch_dims must be <= axis. But instead got: batch_dims =")); } catch (...) { From d2fb57dfe0611e186f354ce3411446fde05c91f3 Mon Sep 17 00:00:00 2001 From: Aleksandr Pertovsky Date: Mon, 17 May 2021 08:45:34 +0300 Subject: [PATCH 84/99] [CPU] Add DFT/IDFT ops (#5383) --- .../src/mkldnn_plugin/mkldnn_node.cpp | 2 + .../src/mkldnn_plugin/mkldnn_node.h | 3 + .../mkldnn_plugin/nodes/mkldnn_dft_node.cpp | 420 ++++++++++++++++++ .../src/mkldnn_plugin/nodes/mkldnn_dft_node.h | 45 ++ .../single_layer_tests/dft.cpp | 107 +++++ .../skip_tests_config.cpp | 2 + .../shared/include/single_layer_tests/dft.hpp | 15 + .../shared_test_classes/single_layer/dft.hpp | 31 ++ .../src/single_layer/dft.cpp | 47 ++ .../include/ngraph_functions/builders.hpp | 4 + .../ngraph_functions/utils/ngraph_helpers.hpp | 5 + .../ngraph_functions/src/dft.cpp | 40 ++ ngraph/python/tests/__init__.py | 3 - ngraph/python/tests/test_ngraph/test_dft.py | 42 +- ngraph/python/tests/test_ngraph/test_idft.py | 40 +- 15 files changed, 759 insertions(+), 47 deletions(-) create mode 100644 inference-engine/src/mkldnn_plugin/nodes/mkldnn_dft_node.cpp create mode 100644 inference-engine/src/mkldnn_plugin/nodes/mkldnn_dft_node.h create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/dft.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/single_layer_tests/dft.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/dft.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/src/single_layer/dft.cpp create mode 100644 inference-engine/tests/ngraph_helpers/ngraph_functions/src/dft.cpp diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_node.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_node.cpp index 1692c411dfe..68addf01231 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_node.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_node.cpp @@ -177,6 +177,8 @@ static const InferenceEngine::details::caseless_unordered_map { "RegionYolo", RegionYolo}, { "Select", Select}, { "ShuffleChannels", ShuffleChannels}, + { "DFT", DFT}, + { "IDFT", DFT} }; Type TypeFromName(const std::string type) { diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_node.h b/inference-engine/src/mkldnn_plugin/mkldnn_node.h index a592f785541..0d0550fe03e 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_node.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_node.h @@ -92,6 +92,7 @@ enum Type { Roll, Reference, ShuffleChannels, + DFT, }; Type TypeFromName(const std::string type); @@ -206,6 +207,8 @@ static std::string NameFromType(Type type) { return "Roll"; case ShuffleChannels: return "ShuffleChannels"; + case DFT: + return "DFT"; default: return "Unknown"; } diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_dft_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_dft_node.cpp new file mode 100644 index 00000000000..21fb93728c1 --- /dev/null +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_dft_node.cpp @@ -0,0 +1,420 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include + +#include "mkldnn_dft_node.h" +#include "ie_parallel.hpp" +#include "ie_precision.hpp" +#include "mkldnn/ie_mkldnn.h" +#include "utils/general_utils.h" +#include "common/cpu_memcpy.h" +#include + +using namespace mkldnn; +using namespace MKLDNNPlugin; +using namespace InferenceEngine; + +bool MKLDNNDFTNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { + try { + const auto interpDFT = std::dynamic_pointer_cast(op); + const auto interpIDFT = std::dynamic_pointer_cast(op); + + if (!interpDFT && !interpIDFT) { + errorMessage = "Only opset7 DFT/IDFT operation is supported"; + return false; + } + } catch (...) { + return false; + } + return true; +} + +MKLDNNDFTNode::MKLDNNDFTNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache) : + MKLDNNNode(op, eng, cache) { + std::string errorMessage; + if (!isSupportedOperation(op, errorMessage)) { + IE_THROW(NotImplemented) << errorMessage; + } + + layerErrorPrefix = "DFT layer with name '" + op->get_name() + "'"; + const size_t inputsNumber = getOriginalInputsNumber(); + if (inputsNumber != 2 && inputsNumber != 3) { + IE_THROW() << layerErrorPrefix << " has invalid number of input/output edges: " << inputsNumber; + } + + /* Data */ + inputShape = inDims[DATA_INDEX].ToSizeVector(); + if (inputShape.size() < 1) { + IE_THROW() << layerErrorPrefix << " has invalid 'data' input tensor with rank: " << inputShape.size(); + } + + /* Axes */ + const auto axesRank = inDims[AXES_INDEX].ndims(); + if (axesRank != 1) { + IE_THROW() << layerErrorPrefix << " has invalid 'axes' input tensor with rank: " << axesRank; + } + + /* Signal size */ + if (inputsNumber > SIGNAL_SIZE_INDEX) { + const auto signalSizeRank = inDims[SIGNAL_SIZE_INDEX].ndims(); + if (signalSizeRank != 1) { + IE_THROW() << layerErrorPrefix << " has invalid 'signal_size' input tensor with rank: " << signalSizeRank; + } + } + + inverse = std::dynamic_pointer_cast(op) == nullptr; +} + +void MKLDNNDFTNode::getSupportedDescriptors() {} + +void MKLDNNDFTNode::initSupportedPrimitiveDescriptors() { + if (!supportedPrimitiveDescriptors.empty()) + return; + + const auto& dataPrecision = getOriginalInputPrecisionAtPort(DATA_INDEX); + if (!dataPrecision.is_float()) { + IE_THROW() << layerErrorPrefix << " has unsupported 'data' input precision: " << dataPrecision.name(); + } + + const auto& axesPrecision = getOriginalInputPrecisionAtPort(AXES_INDEX); + if (axesPrecision != Precision::I32 && axesPrecision != Precision::I64) { + IE_THROW() << layerErrorPrefix << " has unsupported 'axes' input precision: " << axesPrecision.name(); + } + + if (getOriginalInputsNumber() > SIGNAL_SIZE_INDEX) { + const auto& signalSizeTensorPrec = getOriginalInputPrecisionAtPort(SIGNAL_SIZE_INDEX); + if (signalSizeTensorPrec != Precision::I32 && signalSizeTensorPrec != Precision::I64) { + IE_THROW() << layerErrorPrefix << " has unsupported 'signal_size' input precision: " << signalSizeTensorPrec.name(); + } + } + + std::vector inDataConfigurators({{TensorDescCreatorTypes::ncsp, Precision::FP32}, + {TensorDescCreatorTypes::ncsp, Precision::I32}}); + if (getOriginalInputsNumber() > SIGNAL_SIZE_INDEX) + inDataConfigurators.push_back({TensorDescCreatorTypes::ncsp, Precision::I32}); + + addSupportedPrimDesc(inDataConfigurators, {{TensorDescCreatorTypes::ncsp, Precision::FP32}}, impl_desc_type::ref_any); +} + +namespace { +inline float getRealFromComplexProd(float lhsReal, float lhsImag, float rhsReal, float rhsImag) { + return lhsReal * rhsReal - lhsImag * rhsImag; +} + +inline float getImaginaryFromComplexProd(float lhsReal, float lhsImag, float rhsReal, float rhsImag) { + return lhsReal * rhsImag + lhsImag * rhsReal; +} + +/* + Returns true while we can iterate + Specified axis is skipped in counters +*/ +inline bool nextIterationStep(std::vector& counters, const std::vector& iterationRange, size_t axis) { + auto itCounter = counters.rbegin(); + auto itWork = iterationRange.rbegin(); + + while (itCounter != counters.rend() && itWork != iterationRange.rend()) { + if (std::distance(itCounter, counters.rend()) == axis + 1) { + ++itCounter; + ++itWork; + continue; + } + *itCounter = (*itCounter + 1) % *itWork; + if (*itCounter != 0) { + return true; + } + ++itCounter; + ++itWork; + } + return false; +} + +inline bool IsPowerOfTwo(size_t n) { + return (n != 0) && (n & (n - 1)) == 0; +} + +inline bool copyStep(std::vector& counters, const std::vector& iterationRange) { + auto itCounter = counters.rbegin(); + auto itWork = iterationRange.rbegin(); + + while (itCounter != counters.rend() && itWork != iterationRange.rend()) { + *itCounter = (*itCounter + 1) % *itWork; + if (*itCounter != 0) { + return true; + } + ++itCounter; + ++itWork; + } + return false; +} + +size_t calculateOffsetFromStrides(const std::vector& coords, const std::vector& strides) { + size_t offset = 0; + for (size_t index = 0; index < coords.size(); ++index) { + offset += coords[index] * strides[index]; + } + return offset; +} + +void gatherToBufferND(float* buffer, const float* data, size_t axis, const std::vector& dimIndexes, + const std::vector& shape, const std::vector& strides) { + size_t numberOfComplex = shape[axis]; + size_t offset = calculateOffsetFromStrides(dimIndexes, strides); + + for (size_t bufferIndex = 0; bufferIndex < 2 * numberOfComplex; bufferIndex += 2) { + buffer[bufferIndex] = data[offset]; + buffer[bufferIndex + 1] = data[offset + 1]; + offset += strides[axis]; + } +} + +void applyBufferND(const float* buffer, float* output, size_t axis, const std::vector& dimIndexes, + const std::vector& shape, const std::vector& strides) { + size_t numberOfComplex = shape[axis]; + size_t offset = calculateOffsetFromStrides(dimIndexes, strides); + + for (size_t bufferIndex = 0; bufferIndex < 2 * numberOfComplex; bufferIndex += 2) { + output[offset] = buffer[bufferIndex]; + output[offset + 1] = buffer[bufferIndex + 1]; + offset += strides[axis]; + } +} + +void copyDataToOutputWithSignalSize(const float* input, const std::vector& inputShape, const std::vector& inputStrides, + float* output, const std::vector& outputShape, const std::vector& outputStrides) { + auto totalInput = std::accumulate(inputShape.begin(), inputShape.end(), 1, std::multiplies()); + auto totalOutput = std::accumulate(outputShape.begin(), outputShape.end(), 1, std::multiplies()); + std::fill_n(output, totalOutput, 0); + size_t lastChangedDim = 0; + for (size_t index = inputShape.size() - 1; index > 0; --index) { + if (inputShape[index] != outputShape[index]) { + lastChangedDim = index; + break; + } + } + if (lastChangedDim == 0) { + size_t outputBytesSize = std::min(totalOutput, totalInput) * sizeof(float); + cpu_memcpy(output, input, outputBytesSize); + return; + } + + std::vector iterationRange(lastChangedDim + 1, 0); + for (size_t index = 0; index < lastChangedDim + 1; ++index) { + iterationRange[index] = std::min(inputShape[index], outputShape[index]); + } + + const std::vector inputStridesRange(inputStrides.begin(), inputStrides.begin() + iterationRange.size()); + const std::vector outputStridesRange(outputStrides.begin(), outputStrides.begin() + iterationRange.size()); + const size_t blockSize = std::accumulate(inputShape.begin() + lastChangedDim + 1, inputShape.end(), 1ul, std::multiplies()); + const size_t blockSizeBytes = blockSize * sizeof(float); + std::vector iterationCounter(iterationRange.size(), 0); + do { + size_t offsetInput = calculateOffsetFromStrides(iterationCounter, inputStrides); + size_t offsetOutput = calculateOffsetFromStrides(iterationCounter, outputStrides); + cpu_memcpy(output + offsetOutput, input + offsetInput, blockSizeBytes); + } while (copyStep(iterationCounter, iterationRange)); +} + +} // namespace + +void MKLDNNDFTNode::execute(mkldnn::stream strm) { + auto axesEdge = getParentEdgeAt(AXES_INDEX); + const auto* axesStartPtr = reinterpret_cast(axesEdge->getMemoryPtr()->GetPtr()); + axes = std::vector(axesStartPtr, axesStartPtr + axesEdge->getDims()[0]); + for (auto& axis : axes) { + if (axis < 0) { + axis += inputShape.size() - 1; + } + } + std::sort(axes.begin(), axes.end()); + + outputShape = getChildEdgeAt(0)->getDims().ToSizeVector(); + for (size_t axis : axes) { + size_t nComplex = outputShape[axis]; + // FFT uses different twiddle factors + if (twiddlesMap.find(nComplex) == twiddlesMap.end() && !IsPowerOfTwo(nComplex)) { + twiddlesMap[nComplex] = generateTwiddles(nComplex); + } + } + + auto inputDataEdge = getParentEdgeAt(DATA_INDEX); + auto outputDataEdge = getChildEdgeAt(0); + const auto *input = reinterpret_cast(inputDataEdge->getMemoryPtr()->GetPtr()); + auto *output = reinterpret_cast(outputDataEdge->getMemoryPtr()->GetPtr()); + + auto inputStrides = inputDataEdge->getDesc().getBlockingDesc().getStrides(); + auto outputStrides = outputDataEdge->getDesc().getBlockingDesc().getStrides(); + if (inputShape != outputShape) { + copyDataToOutputWithSignalSize(input, inputShape, inputStrides, output, outputShape, outputStrides); + } else { + auto totalElements = std::accumulate(inputShape.begin(), inputShape.end(), 1, std::multiplies()); + cpu_memcpy(output, input, totalElements * sizeof(float)); + } + + // 1d case + if (inputDataEdge->getDesc().getDims().size() == 2) { + size_t nComplex = outputShape[0]; + if (IsPowerOfTwo(nComplex)) { + fft(output, nComplex * 2, true); + } else { + naiveDFT(output, nComplex * 2); + } + } else { + dftNd(output, outputStrides); + } +} + +void MKLDNNDFTNode::dftNd(float* output, const std::vector& outputStrides) const { + const std::vector iterationRange(outputShape.begin(), outputShape.end() - 1); + const size_t lastDimIndex = iterationRange.size() - 1; + for (size_t axisIndex = 0; axisIndex < axes.size(); ++axisIndex) { + const size_t currentAxis = axes[axisIndex]; + const size_t outputComplexLen = outputShape[currentAxis]; + const size_t outputLen = outputComplexLen * 2; + + std::vector iterationCounter(iterationRange.size(), 0); + if (IsPowerOfTwo(outputComplexLen)) { + size_t parallelDimIndex = lastDimIndex == currentAxis ? lastDimIndex - 1 : lastDimIndex; + do { + parallel_for(iterationRange[parallelDimIndex], [&](size_t dim) { + std::vector gatheredData(outputLen); + auto parallelIterationCounter = iterationCounter; + parallelIterationCounter[parallelDimIndex] = dim; + gatherToBufferND(gatheredData.data(), output, currentAxis, parallelIterationCounter, outputShape, outputStrides); + fft(gatheredData.data(), outputLen); + applyBufferND(gatheredData.data(), output, currentAxis, parallelIterationCounter, outputShape, outputStrides); + }); + iterationCounter[parallelDimIndex] = iterationRange[parallelDimIndex] - 1; + } while (nextIterationStep(iterationCounter, iterationRange, currentAxis)); + } else { + std::vector gatheredData(outputLen); + do { + gatherToBufferND(gatheredData.data(), output, currentAxis, iterationCounter, outputShape, outputStrides); + naiveDFT(gatheredData.data(), outputLen); + applyBufferND(gatheredData.data(), output, currentAxis, iterationCounter, outputShape, outputStrides); + } while (nextIterationStep(iterationCounter, iterationRange, currentAxis)); + } + } +} + +/* Cooley Tukey implementation of FFT */ +void MKLDNNDFTNode::fft(float* data, int64_t dataLength, bool parallelize) const { + static int cacheSizeL3 = utils::get_cache_size(3, false); + static int elementsPerCacheLine = cacheSizeL3 / sizeof(float); + std::vector bufferVector(dataLength * 2, 0); + float* buffer = bufferVector.data(); + cpu_memcpy(buffer, data, dataLength * sizeof(float)); + + size_t nComplex = dataLength / 2; + float* inBufferStart = buffer + dataLength; + float* outBufferStart = buffer; + + auto blockIteration = [&] (const size_t block, const size_t blockSize, const size_t nextIterationBlockSize, const float anglePart) { + float* curInpBufferPtr = inBufferStart + block * blockSize; + float* curOutBufferPtr = outBufferStart + block * nextIterationBlockSize; + + const float angle = anglePart * block; + const float twiddleReal = std::cos(angle); + const float twiddleImag = -std::sin(angle); + for (int64_t pair = 0; pair < blockSize / 2; pair += 2) { + const float evenReal = curInpBufferPtr[pair]; + const float evenImag = curInpBufferPtr[pair + 1]; + + const float oddReal = curInpBufferPtr[(blockSize / 2 + pair)]; + const float oddImag = curInpBufferPtr[(blockSize / 2 + pair) + 1]; + + const float twiddledOddReal = getRealFromComplexProd(twiddleReal, twiddleImag, oddReal, oddImag); + const float twiddledOddImag = getImaginaryFromComplexProd(twiddleReal, twiddleImag, oddReal, oddImag); + + curOutBufferPtr[pair] = evenReal + twiddledOddReal; + curOutBufferPtr[pair + 1] = evenImag + twiddledOddImag; + + curOutBufferPtr[nComplex + pair] = evenReal - twiddledOddReal; + curOutBufferPtr[nComplex + pair + 1] = evenImag - twiddledOddImag; + } + }; + + for (int64_t numBlocks = 1; numBlocks < nComplex; numBlocks *= 2) { + const float anglePart = PI / numBlocks * (inverse ? -1 : 1); + + std::swap(inBufferStart, outBufferStart); + const int64_t blockSize = dataLength / numBlocks; + const int64_t nextIterationBlockSize = blockSize / 2; + if (parallelize && blockSize >= 4 * elementsPerCacheLine) { + parallel_for(numBlocks, [&] (const size_t block) { + blockIteration(block, blockSize, nextIterationBlockSize, anglePart); + }); + } else { + for (int64_t block = 0; block < numBlocks; ++block) { + blockIteration(block, blockSize, nextIterationBlockSize, anglePart); + } + } + } + + for (int64_t k = 0; k < dataLength; k++) { + if (inverse) { + outBufferStart[k] /= nComplex; + } + data[k] = outBufferStart[k]; + } +} + +void MKLDNNDFTNode::naiveDFT(float* data, size_t dataLength) const { + std::vector outputBuffer(dataLength); + const size_t nComplex = dataLength / 2; + const auto& twiddles = twiddlesMap.find(nComplex)->second; + + parallel_for(nComplex, [&](size_t k) { + float sumReal = 0.0f; + float sumImag = 0.0f; + for (size_t n = 0; n < nComplex; ++n) { + auto it = twiddles[k * nComplex + n]; + float complexReal = it.first; + float complexImag = it.second; + + if (inverse) { + complexImag *= -1; // conjugate + } + float complexProdReal = getRealFromComplexProd(data[2 * n], data[2 * n + 1], complexReal, complexImag); + float complexProdImag = getImaginaryFromComplexProd(data[2 * n], data[2 * n + 1], complexReal, complexImag); + + sumReal += complexProdReal; + sumImag += complexProdImag; + } + + if (inverse) { + sumReal /= nComplex; + sumImag /= nComplex; + } + outputBuffer[k * 2] = sumReal; + outputBuffer[k * 2 + 1] = sumImag; + }); + cpu_memcpy(data, outputBuffer.data(), dataLength * sizeof(float)); +} + +std::vector> MKLDNNDFTNode::generateTwiddles(size_t n_complex) const { + std::vector> twiddles(n_complex * n_complex); + parallel_for(n_complex, [&](const size_t k) { + for (size_t n = 0; n < n_complex; ++n) { + float phase = 2.0f * PI * static_cast(n * k) / static_cast(n_complex); + auto complexReal = std::cos(phase); + auto complexImag = -std::sin(phase); + twiddles[k * n_complex + n] = std::make_pair(complexReal, complexImag); + } + }); + return twiddles; +} + +bool MKLDNNDFTNode::created() const { + return getType() == DFT; +} + +void MKLDNNDFTNode::createPrimitive() {} + + +REG_MKLDNN_PRIM_FOR(MKLDNNDFTNode, DFT) diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_dft_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_dft_node.h new file mode 100644 index 00000000000..12d23dd5bce --- /dev/null +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_dft_node.h @@ -0,0 +1,45 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +namespace MKLDNNPlugin { + +class MKLDNNDFTNode : public MKLDNNNode { +public: + MKLDNNDFTNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); + ~MKLDNNDFTNode() override = default; + + void getSupportedDescriptors() override; + void initSupportedPrimitiveDescriptors() override; + void createPrimitive() override; + void execute(mkldnn::stream strm) override; + bool created() const override; + + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; + +private: + void dftNd(float* output, const std::vector& outputStrides) const; + void fft(float* data, int64_t dataLength, bool parallelize = false) const; + void naiveDFT(float* data, size_t dataLength) const; + + std::vector> generateTwiddles(size_t n_complex) const; + + std::unordered_map>> twiddlesMap; + std::vector axes; + std::vector outputShape; + std::vector inputShape; + std::string layerErrorPrefix; + const size_t DATA_INDEX = 0; + const size_t AXES_INDEX = 1; + const size_t SIGNAL_SIZE_INDEX = 2; + static constexpr float PI = 3.141592653589793238462643f; + bool inverse; +}; + +} // namespace MKLDNNPlugin diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/dft.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/dft.cpp new file mode 100644 index 00000000000..27e5f5051dc --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/dft.cpp @@ -0,0 +1,107 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "single_layer_tests/dft.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +const std::vector opTypes = { + ngraph::helpers::DFTOpType::FORWARD, + ngraph::helpers::DFTOpType::INVERSE +}; + +const std::vector inputPrecision = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::BF16 +}; + +const std::vector> inputShapes = { + {10, 4, 20, 32, 2}, + {2, 5, 7, 8, 2}, + {1, 120, 128, 1, 2}, +}; + +/* 1D DFT */ +const std::vector> axes1D = { + {0}, {1}, {2}, {3}, {-2} +}; + +const std::vector> signalSizes1D = { + {}, {16}, {40} +}; + +const auto testCase1D = ::testing::Combine( + ::testing::ValuesIn(inputShapes), + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(axes1D), + ::testing::ValuesIn(signalSizes1D), + ::testing::ValuesIn(opTypes), + ::testing::Values(CommonTestUtils::DEVICE_CPU) +); + +/* 2D DFT */ + +const std::vector> axes2D = { + {0, 1}, {2, 1}, {2, 3}, {2, 0}, {1, 3}, {-1, -2} +}; +const std::vector> signalSizes2D = { + {}, {5, 7}, {4, 10}, {16, 8} +}; + +const auto testCase2D = ::testing::Combine( + ::testing::ValuesIn(inputShapes), + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(axes2D), + ::testing::ValuesIn(signalSizes2D), + ::testing::ValuesIn(opTypes), + ::testing::Values(CommonTestUtils::DEVICE_CPU) +); + + +/* 3D DFT */ + +const std::vector> axes3D = { + {0, 1, 2}, {1, 2, 3}, {0, 2, 3}, {2, 3, 1}, {-3, -1, -2}, +}; + +const std::vector> signalSizes3D = { + {}, {4, 8, 16}, {7, 11, 32} +}; + +const auto testCase3D = ::testing::Combine( + ::testing::ValuesIn(inputShapes), + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(axes3D), + ::testing::ValuesIn(signalSizes3D), + ::testing::ValuesIn(opTypes), + ::testing::Values(CommonTestUtils::DEVICE_CPU) +); + +/* 4D DFT */ + +const std::vector> axes4D = { + {0, 1, 2, 3}, {-1, 2, 0, 1} +}; + +const std::vector> signalSizes4D = { + {}, {5, 2, 5, 2} +}; + +const auto testCase4D = ::testing::Combine( + ::testing::ValuesIn(inputShapes), + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(axes4D), + ::testing::ValuesIn(signalSizes4D), + ::testing::ValuesIn(opTypes), + ::testing::Values(CommonTestUtils::DEVICE_CPU) +); + + +INSTANTIATE_TEST_CASE_P(smoke_MKLDNN_TestsDFT_1d, DFTLayerTest, testCase1D, DFTLayerTest::getTestCaseName); +INSTANTIATE_TEST_CASE_P(smoke_MKLDNN_TestsDFT_2d, DFTLayerTest, testCase2D, DFTLayerTest::getTestCaseName); +INSTANTIATE_TEST_CASE_P(smoke_MKLDNN_TestsDFT_3d, DFTLayerTest, testCase3D, DFTLayerTest::getTestCaseName); +INSTANTIATE_TEST_CASE_P(smoke_MKLDNN_TestsDFT_4d, DFTLayerTest, testCase4D, DFTLayerTest::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp index c8afd43d056..ef4cbf639bf 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp @@ -68,6 +68,8 @@ std::vector disabledTestPatterns() { // AUTO plugin and QueryNetwork R"(.*CoreThreading.*smoke_QueryNetwork.*targetDevice=AUTO_config.*)", + // incorrect reference implementation. Issues: 55384, 54528, 54529 + R"(.*DFTLayerTest.*)", }; if (!InferenceEngine::with_cpu_x86_avx512_core()) { diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/dft.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/dft.hpp new file mode 100644 index 00000000000..e985e292438 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/dft.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "shared_test_classes/single_layer/dft.hpp" + +namespace LayerTestsDefinitions { + +TEST_P(DFTLayerTest, CompareWithRefs) { + Run(); +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/dft.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/dft.hpp new file mode 100644 index 00000000000..9f46000fc56 --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/dft.hpp @@ -0,0 +1,31 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include "shared_test_classes/base/layer_test_utils.hpp" +#include "ngraph_functions/builders.hpp" + +namespace LayerTestsDefinitions { + +typedef std::tuple< + InferenceEngine::SizeVector, // Input shapes + InferenceEngine::Precision, // Input precision + std::vector, // Axes + std::vector, // Signal size + ngraph::helpers::DFTOpType, + std::string> DFTParams; // Device name + +class DFTLayerTest : public testing::WithParamInterface, virtual public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj); + +protected: + void SetUp() override; +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/dft.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/dft.cpp new file mode 100644 index 00000000000..28b3b0b11dc --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/dft.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/single_layer/dft.hpp" + +namespace LayerTestsDefinitions { + +std::string DFTLayerTest::getTestCaseName(testing::TestParamInfo obj) { + InferenceEngine::SizeVector inputShapes; + InferenceEngine::Precision inputPrecision; + std::vector axes; + std::vector signalSize; + ngraph::helpers::DFTOpType opType; + std::string targetDevice; + std::tie(inputShapes, inputPrecision, axes, signalSize, opType, targetDevice) = obj.param; + + std::ostringstream result; + result << "IS=" << CommonTestUtils::vec2str(inputShapes) << "_"; + result << "Precision=" << inputPrecision.name() << "_"; + result << "Axes=" << CommonTestUtils::vec2str(axes) << "_"; + result << "SignalSize=" << CommonTestUtils::vec2str(signalSize) << "_"; + result << "Inverse=" << (opType == ngraph::helpers::DFTOpType::INVERSE) << "_"; + result << "TargetDevice=" << targetDevice; + return result.str(); +} + +void DFTLayerTest::SetUp() { + InferenceEngine::SizeVector inputShapes; + InferenceEngine::Precision inputPrecision; + std::vector axes; + std::vector signalSize; + ngraph::helpers::DFTOpType opType; + std::tie(inputShapes, inputPrecision, axes, signalSize, opType, targetDevice) = this->GetParam(); + auto inType = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inputPrecision); + ngraph::ParameterVector paramVector; + auto paramData = std::make_shared(inType, ngraph::Shape(inputShapes)); + paramVector.push_back(paramData); + + auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(paramVector)); + auto dft = ngraph::builder::makeDFT(paramOuts[0], axes, signalSize, opType); + + + ngraph::ResultVector results{std::make_shared(dft)}; + function = std::make_shared(results, paramVector, "DFT"); +} +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp index 18e71981376..475bbdd2ac6 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp @@ -509,5 +509,9 @@ std::shared_ptr makeRoll(const ngraph::Output& dataNode, const ngraph::Output& shiftNode, const ngraph::Output& axesNode); +std::shared_ptr makeDFT(const ngraph::Output &dataNode, + const std::vector &axes, + const std::vector &signalSize, + const ngraph::helpers::DFTOpType opType); } // namespace builder } // namespace ngraph diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/ngraph_helpers.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/ngraph_helpers.hpp index 32aa7ab3e97..cc0afa4eb04 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/ngraph_helpers.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/ngraph_helpers.hpp @@ -180,6 +180,11 @@ enum ReductionType { L2 }; +enum class DFTOpType { + FORWARD, + INVERSE +}; + enum class InputLayerType { CONSTANT, PARAMETER, diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/dft.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/dft.cpp new file mode 100644 index 00000000000..766ae00c88e --- /dev/null +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/dft.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "ngraph_functions/builders.hpp" + +namespace ngraph { +namespace builder { + +namespace { + template + std::shared_ptr CallDftCtorWithArgs(const ngraph::helpers::DFTOpType opType, Args&&... args) { + switch (opType) { + case ngraph::helpers::DFTOpType::FORWARD: + return std::make_shared(std::forward(args)...); + case ngraph::helpers::DFTOpType::INVERSE: + return std::make_shared(std::forward(args)...); + default: + throw std::logic_error("Unsupported operation type"); + } + } +} // namespace + +std::shared_ptr makeDFT(const ngraph::Output &dataNode, + const std::vector &axes, + const std::vector &signalSize, + const ngraph::helpers::DFTOpType opType) { + auto axesNode = std::make_shared(ngraph::element::Type_t::i64, ngraph::Shape{axes.size()}, axes)->output(0); + + if (!signalSize.empty()) { + auto signalSizeNode = std::make_shared(ngraph::element::Type_t::i64, ngraph::Shape{signalSize.size()}, signalSize)->output(0); + return CallDftCtorWithArgs(opType, dataNode, axesNode, signalSizeNode); + } + return CallDftCtorWithArgs(opType, dataNode, axesNode); +} +} // namespace builder +} // namespace ngraph diff --git a/ngraph/python/tests/__init__.py b/ngraph/python/tests/__init__.py index 3fd4136dd3c..5b487cacbc9 100644 --- a/ngraph/python/tests/__init__.py +++ b/ngraph/python/tests/__init__.py @@ -156,7 +156,4 @@ xfail_issue_49754 = xfail_test(reason="RuntimeError: Unsupported dynamic ops: v1 xfail_issue_52463 = xfail_test(reason="test_operator_add_size1_singleton_broadcast_cpu - " "Not equal to tolerance") -xfail_issue_49391 = xfail_test(reason="Roll is not implemented in CPU plugin.") -xfail_issue_49359 = xfail_test(reason="DFT is not implemented in CPU plugin") -xfail_issue_49375 = xfail_test(reason="IDFT is not implemented in CPU plugin") xfail_issue_45432 = xfail_test(reason="Einsum is not implemented in CPU plugin.") diff --git a/ngraph/python/tests/test_ngraph/test_dft.py b/ngraph/python/tests/test_ngraph/test_dft.py index 465aa383567..27645f02958 100644 --- a/ngraph/python/tests/test_ngraph/test_dft.py +++ b/ngraph/python/tests/test_ngraph/test_dft.py @@ -1,6 +1,5 @@ import ngraph as ng import numpy as np -from tests import xfail_issue_49359 from tests.runtime import get_runtime @@ -9,7 +8,6 @@ def build_fft_input_data(): return np.random.uniform(0, 1, (2, 10, 10, 2)).astype(np.float32) -@xfail_issue_49359 def test_dft_1d(): runtime = get_runtime() input_data = build_fft_input_data() @@ -19,12 +17,12 @@ def test_dft_1d(): dft_node = ng.dft(input_tensor, input_axes) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.fft(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), axis=2) - expected_results = np_results.view(dtype=np.float32).reshape((2, 10, 10, 2)) + np_results = np.fft.fft(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), + axis=2).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.00001) -@xfail_issue_49359 def test_dft_2d(): runtime = get_runtime() input_data = build_fft_input_data() @@ -34,12 +32,12 @@ def test_dft_2d(): dft_node = ng.dft(input_tensor, input_axes) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.fft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), axes=[1, 2]) - expected_results = np_results.view(dtype=np.float32).reshape((2, 10, 10, 2)) + np_results = np.fft.fft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), + axes=[1, 2]).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.000062) -@xfail_issue_49359 def test_dft_3d(): runtime = get_runtime() input_data = build_fft_input_data() @@ -49,12 +47,12 @@ def test_dft_3d(): dft_node = ng.dft(input_tensor, input_axes) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.fftn(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), axes=[0, 1, 2]) - expected_results = np_results.view(dtype=np.float32).reshape((2, 10, 10, 2)) + np_results = np.fft.fftn(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), + axes=[0, 1, 2]).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.0002) -@xfail_issue_49359 def test_dft_1d_signal_size(): runtime = get_runtime() input_data = build_fft_input_data() @@ -65,12 +63,12 @@ def test_dft_1d_signal_size(): dft_node = ng.dft(input_tensor, input_axes, input_signal_size) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.fft(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), n=20, axis=-2) - expected_results = np_results.view(dtype=np.float32).reshape((2, 20, 10, 2)) + np_results = np.fft.fft(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), n=20, + axis=-2).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.00001) -@xfail_issue_49359 def test_dft_2d_signal_size_1(): runtime = get_runtime() input_data = build_fft_input_data() @@ -81,12 +79,12 @@ def test_dft_2d_signal_size_1(): dft_node = ng.dft(input_tensor, input_axes, input_signal_size) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.fft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), s=[4, 5], axes=[0, 2]) - expected_results = np_results.view(dtype=np.float32).reshape((4, 10, 5, 2)) + np_results = np.fft.fft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), s=[4, 5], + axes=[0, 2]).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.000062) -@xfail_issue_49359 def test_dft_2d_signal_size_2(): runtime = get_runtime() input_data = build_fft_input_data() @@ -97,12 +95,12 @@ def test_dft_2d_signal_size_2(): dft_node = ng.dft(input_tensor, input_axes, input_signal_size) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.fft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), s=[4, 5], axes=[1, 2]) - expected_results = np_results.view(dtype=np.float32).reshape((2, 4, 5, 2)) + np_results = np.fft.fft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), s=[4, 5], + axes=[1, 2]).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.000062) -@xfail_issue_49359 def test_dft_3d_signal_size(): runtime = get_runtime() input_data = build_fft_input_data() @@ -114,6 +112,6 @@ def test_dft_3d_signal_size(): computation = runtime.computation(dft_node) dft_results = computation() np_results = np.fft.fftn(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), - s=[4, 5, 16], axes=[0, 1, 2]) - expected_results = np_results.view(dtype=np.float32).reshape((4, 5, 16, 2)) + s=[4, 5, 16], axes=[0, 1, 2]).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.0002) diff --git a/ngraph/python/tests/test_ngraph/test_idft.py b/ngraph/python/tests/test_ngraph/test_idft.py index ac352707caa..472e8dfb4e5 100644 --- a/ngraph/python/tests/test_ngraph/test_idft.py +++ b/ngraph/python/tests/test_ngraph/test_idft.py @@ -1,6 +1,5 @@ import ngraph as ng import numpy as np -from tests import xfail_issue_49375 from tests.runtime import get_runtime @@ -9,12 +8,12 @@ def get_data(): return np.random.uniform(0, 1, (2, 10, 10, 2)).astype(np.float32) -@xfail_issue_49375 def test_idft_1d(): runtime = get_runtime() expected_results = get_data() - complex_input_data = np.fft.fft(np.squeeze(expected_results.view(dtype=np.complex64), axis=-1), axis=2) - input_data = complex_input_data.view(dtype=np.float32).reshape((2, 10, 10, 2)) + complex_input_data = np.fft.fft(np.squeeze(expected_results.view(dtype=np.complex64), + axis=-1), axis=2).astype(np.complex64) + input_data = np.stack((complex_input_data.real, complex_input_data.imag), axis=-1) input_tensor = ng.constant(input_data) input_axes = ng.constant(np.array([2], dtype=np.int64)) @@ -24,13 +23,12 @@ def test_idft_1d(): assert np.allclose(dft_results, expected_results, atol=0.000002) -@xfail_issue_49375 def test_idft_2d(): runtime = get_runtime() expected_results = get_data() complex_input_data = np.fft.fft2(np.squeeze(expected_results.view(dtype=np.complex64), axis=-1), - axes=[1, 2]) - input_data = complex_input_data.view(dtype=np.float32).reshape((2, 10, 10, 2)) + axes=[1, 2]).astype(np.complex64) + input_data = np.stack((complex_input_data.real, complex_input_data.imag), axis=-1) input_tensor = ng.constant(input_data) input_axes = ng.constant(np.array([1, 2], dtype=np.int64)) @@ -40,13 +38,12 @@ def test_idft_2d(): assert np.allclose(dft_results, expected_results, atol=0.000002) -@xfail_issue_49375 def test_idft_3d(): runtime = get_runtime() expected_results = get_data() complex_input_data = np.fft.fft2(np.squeeze(expected_results.view(dtype=np.complex64), axis=-1), - axes=[0, 1, 2]) - input_data = complex_input_data.view(dtype=np.float32).reshape((2, 10, 10, 2)) + axes=[0, 1, 2]).astype(np.complex64) + input_data = np.stack((complex_input_data.real, complex_input_data.imag), axis=-1) input_tensor = ng.constant(input_data) input_axes = ng.constant(np.array([0, 1, 2], dtype=np.int64)) @@ -56,7 +53,6 @@ def test_idft_3d(): assert np.allclose(dft_results, expected_results, atol=0.000003) -@xfail_issue_49375 def test_idft_1d_signal_size(): runtime = get_runtime() input_data = get_data() @@ -67,12 +63,12 @@ def test_idft_1d_signal_size(): dft_node = ng.idft(input_tensor, input_axes, input_signal_size) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.ifft(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), n=20, axis=-2) - expected_results = np_results.view(dtype=np.float32).reshape((2, 20, 10, 2)) + np_results = np.fft.ifft(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), n=20, + axis=-2).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.000002) -@xfail_issue_49375 def test_idft_2d_signal_size_1(): runtime = get_runtime() input_data = get_data() @@ -83,12 +79,12 @@ def test_idft_2d_signal_size_1(): dft_node = ng.idft(input_tensor, input_axes, input_signal_size) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.ifft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), s=[4, 5], axes=[0, 2]) - expected_results = np_results.view(dtype=np.float32).reshape((4, 10, 5, 2)) + np_results = np.fft.ifft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), s=[4, 5], + axes=[0, 2]).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.000002) -@xfail_issue_49375 def test_idft_2d_signal_size_2(): runtime = get_runtime() input_data = get_data() @@ -99,12 +95,12 @@ def test_idft_2d_signal_size_2(): dft_node = ng.idft(input_tensor, input_axes, input_signal_size) computation = runtime.computation(dft_node) dft_results = computation() - np_results = np.fft.fft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), s=[4, 5], axes=[1, 2]) - expected_results = np_results.view(dtype=np.float32).reshape((2, 4, 5, 2)) + np_results = np.fft.ifft2(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), s=[4, 5], + axes=[1, 2]).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.000002) -@xfail_issue_49375 def test_idft_3d_signal_size(): runtime = get_runtime() input_data = get_data() @@ -116,6 +112,6 @@ def test_idft_3d_signal_size(): computation = runtime.computation(dft_node) dft_results = computation() np_results = np.fft.ifftn(np.squeeze(input_data.view(dtype=np.complex64), axis=-1), - s=[4, 5, 16], axes=[0, 1, 2]) - expected_results = np_results.view(dtype=np.float32).reshape((4, 5, 16, 2)) + s=[4, 5, 16], axes=[0, 1, 2]).astype(np.complex64) + expected_results = np.stack((np_results.real, np_results.imag), axis=-1) assert np.allclose(dft_results, expected_results, atol=0.000002) From d5a88614753306cc219eec0a73ff939648a956fa Mon Sep 17 00:00:00 2001 From: Szymon Durawa Date: Mon, 17 May 2021 08:21:07 +0200 Subject: [PATCH 85/99] Update specification for ConvolutionBackpropData. (#4679) * Update specification for ConvolutionBackpropData. * Add backticks to attribute types, changed layout description for input, filter and output. * Correct xml example. * Add new examples. * Add link with convolution backprop description. * Repleace additional link with argxiv website. * Insert enumeration for examples. * Fix example with output_shape input. --- .../convolution/ConvolutionBackpropData_1.md | 111 +++++++++++++++--- 1 file changed, 93 insertions(+), 18 deletions(-) diff --git a/docs/ops/convolution/ConvolutionBackpropData_1.md b/docs/ops/convolution/ConvolutionBackpropData_1.md index e1bbc6bbbb4..f29ce44e259 100644 --- a/docs/ops/convolution/ConvolutionBackpropData_1.md +++ b/docs/ops/convolution/ConvolutionBackpropData_1.md @@ -4,15 +4,15 @@ **Category**: Convolution -**Short description**: Computes the gradients of a Convolution operation with respect to the input. Also known as a Deconvolution or a Transposed Convolution. +**Short description**: Computes 1D, 2D or 3D *ConvolutionBackpropData* operation with respect to the input and kernel tensors. Also known as a Transposed Convolution. **Detailed description**: -ConvolutionBackpropData takes the input tensor, weights tensor and output shape and computes the output tensor of a given shape. The shape of the output can be specified as an input 1D integer tensor explicitly or determined by other attributes implicitly. If output shape is specified as an explicit input, shape of the output exactly matches the specified size and required amount of padding is computed. +ConvolutionBackpropData takes the input tensor, weights tensor and output shape and computes the output tensor of a given shape. The shape of the output can be specified as an input 1D integer tensor explicitly or determined by other attributes implicitly. If output shape is specified as an explicit input, shape of the output exactly matches the specified size and required amount of padding is computed. More thorough explanation can be found in [Transposed Convolutions](https://arxiv.org/abs/1603.07285). -ConvolutionBackpropData accepts the same set of attributes as a regular Convolution operation, but they are interpreted in a "backward way", so they are applied to the output of ConvolutionBackpropData, but not to the input. Refer to a regular Convolution operation for detailed description of each attribute. +ConvolutionBackpropData accepts the same set of attributes as a regular Convolution operation and additionally `output_padding` attribute, but they are interpreted in a "backward way", so they are applied to the output of ConvolutionBackpropData, but not to the input. Refer to a regular [Convolution](Convolution_1.md) operation for detailed description of each Convolution attribute. -Output shape when specified as an input `output_shape`, specifies only spatial dimensions. No batch or channel dimension should be passed along with H, W or other spatial dimensions. If `output_shape` is omitted, then `pads_begin`, `pads_end` or `auto_pad` are used to determine output spatial shape `[Y_1, Y_2, ..., Y_D]` by input spatial shape `[X_1, X_2, ..., X_D]` in the following way: +When output shape is specified as an input tensor `output_shape` then it specifies only spatial dimensions. No batch or channel dimension should be passed along with spatial dimensions. If `output_shape` is omitted, then `pads_begin`, `pads_end` or `auto_pad` are used to determine output spatial shape `[O_z, O_y, O_x]` by input spatial shape `[I_z, I_y, I_x]` in the following way: ``` if auto_pads != None: @@ -24,7 +24,7 @@ Y_i = stride[i] * (X_i - 1) + ((K_i - 1) * dilations[i] + 1) - pads_begin[i] - p where `K_i` filter kernel dimension along spatial axis `i`. - If `output_shape` is specified, `pads_begin` and `pads_end` are ignored, and `auto_pad` defines how to distribute padding amount around the tensor. In this case pads are determined based on the next formulas to correctly align input and output tensors (similar to ONNX definition at https://github.com/onnx/onnx/blob/master/docs/Operators.md#convtranspose): + If `output_shape` is specified, `pads_begin` and `pads_end` are ignored, and `auto_pad` defines how to distribute padding amount around the tensor. In this case pads are determined based on the next formulas to correctly align input and output tensors: ``` total_padding[i] = stride[i] * (X_i - 1) + ((K_i - 1) * dilations[i] + 1) - output_shape[i] + output_padding[i] @@ -42,7 +42,7 @@ else: * **Description**: *strides* has the same definition as *strides* for a regular Convolution but applied in the backward way, for the output tensor. * **Range of values**: positive integers - * **Type**: int[] + * **Type**: `int[]` * **Default value**: None * **Required**: *yes* @@ -50,7 +50,7 @@ else: * **Description**: *pads_begin* has the same definition as *pads_begin* for a regular Convolution but applied in the backward way, for the output tensor. May be omitted specified, in which case pads are calculated automatically. * **Range of values**: non-negative integers - * **Type**: int[] + * **Type**: `int[]` * **Default value**: None * **Required**: *yes* * **Note**: the attribute is ignored when *auto_pad* attribute is specified. @@ -59,7 +59,7 @@ else: * **Description**: *pads_end* has the same definition as *pads_end* for a regular Convolution but applied in the backward way, for the output tensor. May be omitted, in which case pads are calculated automatically. * **Range of values**: non-negative integers - * **Type**: int[] + * **Type**: `int[]` * **Default value**: None * **Required**: *yes* * **Note**: the attribute is ignored when *auto_pad* attribute is specified. @@ -68,7 +68,7 @@ else: * **Description**: *dilations* has the same definition as *dilations* for a regular Convolution but applied in the backward way, for the output tensor. * **Range of values**: positive integers - * **Type**: int[] + * **Type**: `int[]` * **Default value**: None * **Required**: *yes* @@ -76,9 +76,10 @@ else: * **Description**: *auto_pad* has the same definition as *auto_pad* for a regular Convolution but applied in the backward way, for the output tensor. * *explicit*: use explicit padding values from `pads_begin` and `pads_end`. - * *same_upper (same_lower)* the input is padded to match the output size. In case of odd padding value an extra padding is added at the end (at the beginning). + * *same_upper* the input is padded to match the output size. In case of odd padding value an extra padding is added at the end. + * *same_lower* the input is padded to match the output size. In case of odd padding value an extra padding is added at the beginning. * *valid* - do not use padding. - * **Type**: string + * **Type**: `string` * **Default value**: None * **Required**: *no* * **Note**: *pads_begin* and *pads_end* attributes are ignored when *auto_pad* is specified. @@ -87,27 +88,38 @@ else: * **Description**: *output_padding* adds additional amount of paddings per each spatial axis in the `output` tensor. It unlocks more elements in the output allowing them to be computed. Elements are added at the higher coordinate indices for the spatial dimensions. Number of elements in *output_padding* list matches the number of spatial dimensions in `data` and `output` tensors. * **Range of values**: non-negative integer values - * **Type**: int[] + * **Type**: `int[]` * **Default value**: all zeros * **Required**: *no* **Inputs**: -* **1**: `data` -- input tensor of rank 3 or greater. Layout is `[N, C_INPUT, X1, ..., XD]`. *Required*. +* **1**: Input tensor of type *T1* and rank 3, 4 or 5. Layout is `[N, C_INPUT, Z, Y, X]` (number of batches, number of input channels, spatial axes Z, Y, X). *Required*. -* **2**: `filter` -- convolution kernel tensor. Weights have shape `[C_INPUT, C_OUTPUT, K_D, ..., K_1]`. `C_INPUT` is the number of channels in input `data` tensor shape, and `C_OUTPUT` is the number of channels in the `output` tensor. Spatial size of the kernel `[K_D, ..., K_1]` is derived from the shape of this input and aren't specified by any attribute. *Required*. +* **2**: Convolution kernel tensor of type *T1* and rank 3, 4 or 5. Layout is `[C_INPUT, C_OUTPUT, Z, Y, X]` (number of input channels, number of output channels, spatial axes Z, Y, X). Spatial size of the kernel is derived from the shape of this input and aren't specified by any attribute. *Required*. -* **3**: `output_shape` is 1D integer tensor that specifies spatial shape of the output. *Optional*. If specified, *padding amount* is deduced from relation of input and output spatial shapes according to formulas in the description. If not specified, *output shape* is calculated based on the `pads_begin` and `pads_end` or completely according to `auto_pad`. +* **3**: `output_shape` is 1D tensor of type *T2* that specifies spatial shape of the output. If specified, *padding amount* is deduced from relation of input and output spatial shapes according to formulas in the description. If not specified, *output shape* is calculated based on the `pads_begin` and `pads_end` or completely according to `auto_pad`. *Optional*. +* **Note**: Type of the convolution (1D, 2D or 3D) is derived from the rank of the input tensors and not specified by any attribute: + * 1D convolution (input tensors rank 3) means that there is only one spatial axis X, + * 2D convolution (input tensors rank 4) means that there are two spatial axes Y, X, + * 3D convolution (input tensors rank 5) means that there are three spatial axes Z, Y, X. **Outputs**: -* **1**: `output` -- output tensor of the same rank as input `data` tensor and shape `[N, C_OUTPUT, Y1, ..., YD]`. +* **1**: Output tensor of type *T1* and rank 3, 4 or 5. Layout is `[N, C_OUTPUT, Z, Y, X]` (number of batches, number of kernel output channels, spatial axes Z, Y, X). -**Example** +**Types**: + +* *T1*: any numeric type. +* *T2*: any integer type. + +**Examples** + +*Example 1: 2D ConvolutionBackpropData* ```xml - + 1 @@ -132,3 +144,66 @@ else: ``` + +*Example 2: 2D ConvolutionBackpropData with output_padding* + +```xml + + + + + 1 + 20 + 2 + 2 + + + 20 + 10 + 3 + 3 + + + + + 1 + 10 + 8 + 8 + + + +``` + +*Example 3: 2D ConvolutionBackpropData with output_shape input* + +```xml + + + + + 1 + 20 + 224 + 224 + + + 20 + 10 + 3 + 3 + + + 2 + + + + + 1 + 10 + 450 + 450 + + + +``` From 880b45a7702317ab88d5f923e847ac1901743b6e Mon Sep 17 00:00:00 2001 From: Mateusz Bencer Date: Mon, 17 May 2021 10:11:49 +0200 Subject: [PATCH 86/99] Add high level API to ONNX Editor (#4927) --- .../include/onnx_editor/edge_mapper.hpp | 112 +++++ .../include/onnx_editor/editor.hpp | 62 +++ .../include/onnx_editor/editor_types.hpp | 69 +++ .../frontend/onnx_editor/src/edge_mapper.cpp | 243 +++++++++ ngraph/frontend/onnx_editor/src/editor.cpp | 47 ++ .../subgraph__inception_head.prototxt | 6 +- .../subgraph_extraction_tests.prototxt | 5 + .../subgraph_extraction_tests_2.prototxt | 3 + ngraph/test/onnx/onnx_editor.cpp | 475 +++++++++++++++++- 9 files changed, 1017 insertions(+), 5 deletions(-) create mode 100644 ngraph/frontend/onnx_editor/include/onnx_editor/edge_mapper.hpp create mode 100644 ngraph/frontend/onnx_editor/src/edge_mapper.cpp diff --git a/ngraph/frontend/onnx_editor/include/onnx_editor/edge_mapper.hpp b/ngraph/frontend/onnx_editor/include/onnx_editor/edge_mapper.hpp new file mode 100644 index 00000000000..8b91f0c778e --- /dev/null +++ b/ngraph/frontend/onnx_editor/include/onnx_editor/edge_mapper.hpp @@ -0,0 +1,112 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +#include "onnx_editor/editor_types.hpp" + +namespace ONNX_NAMESPACE +{ + // Forward declaration to avoid the necessity of including paths in components + // that don't directly depend on the ONNX library + class GraphProto; +} // namespace ONNX_NAMESPACE + +namespace ngraph +{ + namespace onnx_editor + { + /// \brief A class which allows specifying InputEdge and OutputEdge by user-friendly ONNX + /// names. + class EdgeMapper + { + public: + EdgeMapper() = default; + + /// \brief Creates an edge mapper based on a GraphProto object. + /// + /// \note If state of graph_proto will be changed, the information from edge mapper + /// is outdated. In such a case the update method should be called. + /// + /// \param graph_proto Reference to a GraphProto object. + EdgeMapper(const ONNX_NAMESPACE::GraphProto& graph_proto); + + /// \brief Returns the InputEdge based on a node (node name or output name) + /// and an input (input name or input index). + /// + /// \note The node name can be ambiguous (many ONNX nodes can have the same name). + /// In such a case the algorthim tries to match the given node name + /// with the input name (providing an input index is not enough). + /// If a unique edge is found, it will be returned. + /// If InputEdge cannot be determined based on parameter values an ngraph_error + /// exception will be thrown. + /// + /// \param node An EditorNode helper structure created based on a node name + /// or a node output name. + /// + /// \param input An EditorInput helper structure created based on a input name + /// or a input index. + InputEdge find_input_edge(const EditorNode& node, const EditorInput& input) const; + + /// \brief Returns an OutputEdge based on a node (node name or output name) + /// and an output (output name or output index). + /// + /// \note The node name can be ambiguous (many ONNX nodes can have the same name). + /// In such a case the algorthim will try to match the given node name + /// with the output name (providing an output index is not enough). + /// If after such operation a found edge is unique, it is returned. + /// If OutputEdge cannot be determined based on given params the ngraph_error + /// exception is thrown. + /// + /// \param node An EditorNode helper structure created based on a node name + /// or a node output name. + /// + /// \param output An EditorOutput helper structure created based on a output name + /// or a output index. + OutputEdge find_output_edge(const EditorNode& node, const EditorOutput& output) const; + + /// \brief Returns an OutputEdge based on a output name. + /// + /// \note The output name guarantees the uniqueness of the edge. + /// + /// \param output_name A node output name. + /// + OutputEdge find_output_edge(const std::string& output_name) const; + + /// \brief Returns a vector of InputEdges which consume an output of a node + /// determined by provided output name. + /// + /// \note The output name is deterministic in the ONNX standard. + /// + /// \param output_name A node output name. + /// + std::vector find_output_consumers(const std::string& output_name) const; + + /// \brief Returns true if a provided node is correct (exists in a graph) + /// and is not ambiguous (identification of an ONNX node can be ambiguous + /// if an only tensor name is provided). + /// + /// \param node An EditorNode helper structure created based on a node name + /// or a node output name. + /// + bool is_correct_and_unambiguous_node(const EditorNode& node) const; + + private: + std::vector find_node_indexes(const std::string& node_name, + const std::string& output_name) const; + std::string get_node_input_name(int node_index, int input_index) const; + std::string get_node_output_name(int node_index, int output_index) const; + + std::vector> m_node_inputs; + std::vector> m_node_outputs; + std::multimap m_node_name_to_index; + std::map m_node_output_name_to_index; + std::multimap m_output_consumers_index; + }; + } // namespace onnx_editor +} // namespace ngraph diff --git a/ngraph/frontend/onnx_editor/include/onnx_editor/editor.hpp b/ngraph/frontend/onnx_editor/include/onnx_editor/editor.hpp index 465890cab11..b93b568141e 100644 --- a/ngraph/frontend/onnx_editor/include/onnx_editor/editor.hpp +++ b/ngraph/frontend/onnx_editor/include/onnx_editor/editor.hpp @@ -108,7 +108,69 @@ namespace ngraph /// \param out_file_path A path to the file where the modified model should be dumped. void serialize(const std::string& out_file_path) const; + /// \brief Returns the InputEdge based on a node (node name or output name) + /// and an input (input name or input index). + /// + /// \note The node name can be ambiguous (many ONNX nodes can have the same name). + /// In such a case the algorthim tries to match the given node name + /// with the input name (providing an input index is not enough). + /// If a unique edge is found, it will be returned. + /// If InputEdge cannot be determined based on parameter values an ngraph_error + /// exception will be thrown. + /// + /// \param node A node helper structure created based on a node name + /// or a node output name. + /// + /// \param input An input helper structure created based on a input name + /// or a input index. + InputEdge find_input_edge(const EditorNode& node, const EditorInput& input) const; + + /// \brief Returns an OutputEdge based on a node (node name or output name) + /// and an output (output name or output index). + /// + /// \note The node name can be ambiguous (many ONNX nodes can have the same name). + /// In such a case the algorthim will try to match the given node name + /// with the output name (providing an output index is not enough). + /// If after such operation a found edge is unique, it is returned. + /// If OutputEdge cannot be determined based on given params the ngraph_error + /// exception is thrown. + /// + /// \param node A node helper structure created based on a node name + /// or a node output name. + /// + /// \param output A output helper structure created based on a output name + /// or a output index. + OutputEdge find_output_edge(const EditorNode& node, const EditorOutput& output) const; + + /// \brief Returns an OutputEdge based on a output name. + /// + /// \note The output name guarantees the uniqueness of the edge. + /// + /// \param output_name A node output name. + /// + OutputEdge find_output_edge(const std::string& output_name) const; + + /// \brief Returns a vector of InputEdges which consume an output of a node + /// determined by provided output name. + /// + /// \note The output name is deterministic in the ONNX standard. + /// + /// \param output_name A node output name. + /// + std::vector find_output_consumers(const std::string& output_name) const; + + /// \brief Returns a vector of InputEdges which consume an output of a node + /// determined by provided output name. + /// + /// \note The output name is deterministic in the ONNX standard. + /// + /// \param output_name A node output name. + /// + bool is_correct_and_unambiguous_node(const EditorNode& node) const; + private: + void update_mapper_if_needed() const; + const std::string m_model_path; struct Impl; diff --git a/ngraph/frontend/onnx_editor/include/onnx_editor/editor_types.hpp b/ngraph/frontend/onnx_editor/include/onnx_editor/editor_types.hpp index 56afa34af32..6f941d90869 100644 --- a/ngraph/frontend/onnx_editor/include/onnx_editor/editor_types.hpp +++ b/ngraph/frontend/onnx_editor/include/onnx_editor/editor_types.hpp @@ -60,5 +60,74 @@ namespace ngraph /// OutputEdge(5, "out1") /// OutputEdge(5, "out2") using OutputEdge = Edge; + + /// \brief Specifies a single node input by the name or index. + /// + /// For a node test_node, with 3 inputs: + /// + /// ----(in_A)----> +-----------+ + /// ----(in_B)----> | test_node | ----(out)----> + /// ----(in_C)----> +-----------+ + /// You can indicate in_B as EditorInput("in_B") or EditorInput(1) + struct EditorInput + { + EditorInput() = delete; + EditorInput(std::string input_name) + : m_input_name{std::move(input_name)} + { + } + EditorInput(const int input_index) + : m_input_index{input_index} + { + } + const std::string m_input_name = ""; + const int m_input_index = -1; + }; + + /// \brief Specifies a single node output by the name or index. + /// For a node test_node, with 2 outputs: + /// + /// +-----------+ ---(out1)---> + /// ----(in_A)----> | test_node | + /// +-----------+ ---(out2)---> + /// You can indicate out2 as EditorOutput("out2") or EditorOutput(1) + struct EditorOutput + { + EditorOutput() = delete; + EditorOutput(std::string output_name) + : m_output_name{std::move(output_name)} + { + } + EditorOutput(const int output_index) + : m_output_index{output_index} + { + } + const std::string m_output_name = ""; + const int m_output_index = -1; + }; + + /// \brief Specifies a single node by output name which is determinitic + /// or node name which can be ambiguous. + /// For a node test_node, with 2 outputs: + /// + /// +-----------+ ---(out1)---> + /// ----(in_A)----> | test_node | + /// +-----------+ ---(out2)---> + /// You can indicate test_node by name as EditorNode("test_node") + /// or by assigned output as EditorNode(EditorOutput("out1")) + /// or EditorNode(EditorOutput("out2")) + struct EditorNode + { + EditorNode(std::string node_name) + : m_node_name{std::move(node_name)} + { + } + EditorNode(EditorOutput output) + : m_output_name{std::move(output.m_output_name)} + { + } + const std::string m_node_name = ""; + const std::string m_output_name = ""; + }; } // namespace onnx_editor } // namespace ngraph diff --git a/ngraph/frontend/onnx_editor/src/edge_mapper.cpp b/ngraph/frontend/onnx_editor/src/edge_mapper.cpp new file mode 100644 index 00000000000..eeb244b9842 --- /dev/null +++ b/ngraph/frontend/onnx_editor/src/edge_mapper.cpp @@ -0,0 +1,243 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "ngraph/except.hpp" +#include "onnx_editor/edge_mapper.hpp" + +using namespace ngraph; +using namespace ngraph::onnx_editor; + +onnx_editor::EdgeMapper::EdgeMapper(const ONNX_NAMESPACE::GraphProto& graph_proto) + : m_node_inputs(graph_proto.node().size()) + , m_node_outputs(graph_proto.node().size()) +{ + int topological_index = 0; + for (const auto& node_proto : graph_proto.node()) + { + for (const auto& out_name : node_proto.output()) + { + // node output name is unique + m_node_output_name_to_index.emplace(out_name, topological_index); + m_node_outputs[topological_index].push_back(out_name); + } + for (const auto& in_name : node_proto.input()) + { + m_node_inputs[topological_index].push_back(in_name); + m_output_consumers_index.emplace(in_name, topological_index); + } + if (!node_proto.name().empty()) + { + // node name can identify node, but it can be ambiguous + m_node_name_to_index.emplace(node_proto.name(), topological_index); + } + ++topological_index; + } +} + +std::vector onnx_editor::EdgeMapper::find_node_indexes(const std::string& node_name, + const std::string& output_name) const +{ + if (!output_name.empty()) + { + const auto& index_iter = m_node_output_name_to_index.find(output_name); + if (index_iter != std::end(m_node_output_name_to_index)) + { + return std::vector{index_iter->second}; + } + } + std::vector result; + if (!node_name.empty()) + { + const auto matched_nodes_range = m_node_name_to_index.equal_range(node_name); + std::transform(matched_nodes_range.first, + matched_nodes_range.second, + std::back_inserter(result), + [](const std::pair& iter) { return iter.second; }); + } + return result; +}; + +std::string onnx_editor::EdgeMapper::get_node_output_name(int node_index, int output_index) const +{ + if (node_index >= static_cast(m_node_outputs.size())) + { + throw ngraph_error("Node with index: " + std::to_string(node_index) + + "is out of scope outputs list"); + } + if (output_index >= static_cast(m_node_outputs[node_index].size())) + { + throw ngraph_error("Node with index: " + std::to_string(node_index) + + " has not output with index: " + std::to_string(output_index)); + } + const auto output_name = m_node_outputs[node_index][output_index]; + return output_name; +} + +std::string onnx_editor::EdgeMapper::get_node_input_name(int node_index, int input_index) const +{ + if (node_index >= static_cast(m_node_inputs.size())) + { + throw ngraph_error("Node with index: " + std::to_string(node_index) + + "is out of scope inputs list"); + } + if (input_index >= static_cast(m_node_inputs[node_index].size())) + { + throw ngraph_error("Node with index: " + std::to_string(node_index) + + " has not input with index: " + std::to_string(input_index)); + } + const auto input_name = m_node_inputs[node_index][input_index]; + return input_name; +} + +InputEdge onnx_editor::EdgeMapper::find_input_edge(const EditorNode& node, + const EditorInput& in) const +{ + // identification can be both based on node name and output name + const auto& node_indexes = find_node_indexes(node.m_node_name, node.m_output_name); + int node_index = -1; + if (node_indexes.size() == 1) + { + node_index = node_indexes[0]; + } + else if (node_indexes.empty()) + { + throw ngraph_error( + "Node with name: " + (node.m_node_name.empty() ? "not_given" : node.m_node_name) + + " and output_name: " + (node.m_output_name.empty() ? "not_given" : node.m_output_name) + + " was not found"); + } + else if (!in.m_input_name + .empty()) // input indexes are not deterministic if a node name is ambiguous + { + // many nodes with the same name + // check if some of found index matches input name + int matched_inputs_number = 0; + for (const auto& index : node_indexes) + { + if (std::count(std::begin(m_node_inputs[index]), + std::end(m_node_inputs[index]), + in.m_input_name) > 0) + { + node_index = index; + ++matched_inputs_number; + } + } + if (matched_inputs_number == 0) + { + throw ngraph_error("Input edge described by: " + node.m_node_name + + " and input name: " + in.m_input_name + " was not found"); + } + if (matched_inputs_number > 1) + { + throw ngraph_error("Given node name: " + node.m_node_name + " and input name: " + + in.m_input_name + " are ambiguous to determine input edge"); + } + } + else + { + throw ngraph_error("Given node name: " + node.m_node_name + + " and input index: " + std::to_string(in.m_input_index) + + " are ambiguous to determine input edge"); + } + if (!in.m_input_name.empty()) + { + return InputEdge{node_index, in.m_input_name}; + } + else if (in.m_input_index != -1) // input index is set + { + const auto& input_name = get_node_input_name(node_index, in.m_input_index); + return InputEdge{node_index, input_name}; + } + else + { + throw ngraph_error("Not enough information to determine input edge"); + } +} + +OutputEdge onnx_editor::EdgeMapper::find_output_edge(const EditorNode& node, + const EditorOutput& out) const +{ + // identification can be both based on node name and output name + const auto& node_indexes = find_node_indexes(node.m_node_name, node.m_output_name); + int node_index = -1; + if (node_indexes.size() == 1) + { + node_index = node_indexes[0]; + } + else if (node_indexes.empty()) + { + throw ngraph_error( + "Node with name: " + (node.m_node_name.empty() ? "not_given" : node.m_node_name) + + " and output_name: " + (node.m_output_name.empty() ? "not_given" : node.m_output_name) + + " was not found"); + } + else if (!out.m_output_name + .empty()) // output indexes are not deterministic if a node name is ambiguous + { + // many nodes with the same name + // check if some of found index matches output name + int matched_outputs_number = 0; + for (const auto& index : node_indexes) + { + if (std::count(std::begin(m_node_outputs[index]), + std::end(m_node_outputs[index]), + out.m_output_name) > 0) + { + node_index = index; + ++matched_outputs_number; + } + } + if (matched_outputs_number == 0) + { + throw ngraph_error("Output edge described by: " + node.m_node_name + + " and output name: " + out.m_output_name + " was not found"); + } + } + else + { + throw ngraph_error("Given node name: " + node.m_node_name + + " and output index: " + std::to_string(out.m_output_index) + + " are ambiguous to determine output edge"); + } + if (!out.m_output_name.empty()) + { + return OutputEdge{node_index, out.m_output_name}; + } + else if (out.m_output_index != -1) // output index is set + { + const auto& output_name = get_node_output_name(node_index, out.m_output_index); + return OutputEdge{node_index, output_name}; + } + else + { + throw ngraph_error("Not enough information to determine output edge"); + } +} + +OutputEdge onnx_editor::EdgeMapper::find_output_edge(const std::string& output_name) const +{ + return find_output_edge(EditorNode{EditorOutput{output_name}}, EditorOutput{output_name}); +} + +std::vector + onnx_editor::EdgeMapper::find_output_consumers(const std::string& output_name) const +{ + const auto matched_nodes_range = m_output_consumers_index.equal_range(output_name); + std::vector input_edges; + std::transform(matched_nodes_range.first, + matched_nodes_range.second, + std::back_inserter(input_edges), + [&output_name](const std::pair& iter) { + return InputEdge{iter.second, output_name}; + }); + return input_edges; +} + +bool onnx_editor::EdgeMapper::is_correct_and_unambiguous_node(const EditorNode& node) const +{ + return find_node_indexes(node.m_node_name, node.m_output_name).size() == 1; +} diff --git a/ngraph/frontend/onnx_editor/src/editor.cpp b/ngraph/frontend/onnx_editor/src/editor.cpp index 566659e6633..778b8261cee 100644 --- a/ngraph/frontend/onnx_editor/src/editor.cpp +++ b/ngraph/frontend/onnx_editor/src/editor.cpp @@ -10,10 +10,12 @@ #include "ngraph/log.hpp" #include "onnx_common/parser.hpp" #include "onnx_common/utils.hpp" +#include "onnx_editor/edge_mapper.hpp" #include "onnx_editor/editor.hpp" #include "onnx_import/utils/onnx_internal.hpp" using namespace ngraph; +using namespace ngraph::onnx_editor; namespace { @@ -186,6 +188,8 @@ namespace struct onnx_editor::ONNXModelEditor::Impl { ONNX_NAMESPACE::ModelProto m_model_proto; + EdgeMapper m_edge_mapper; + bool m_is_mapper_updated = false; Impl() = delete; @@ -285,6 +289,7 @@ void onnx_editor::ONNXModelEditor::cut_graph_fragment(const std::vectorremove_shape_inference_info(); + m_pimpl->m_is_mapper_updated = false; } std::vector onnx_editor::ONNXModelEditor::model_inputs() const @@ -344,3 +349,45 @@ void onnx_editor::ONNXModelEditor::set_input_values( modify_initializer(*onnx_initializer, name, values, onnx_input); } } + +void onnx_editor::ONNXModelEditor::update_mapper_if_needed() const +{ + if (!m_pimpl->m_is_mapper_updated) + { + m_pimpl->m_edge_mapper = EdgeMapper(m_pimpl->m_model_proto.graph()); + } + m_pimpl->m_is_mapper_updated = true; +} + +InputEdge onnx_editor::ONNXModelEditor::find_input_edge(const EditorNode& node, + const EditorInput& input) const +{ + update_mapper_if_needed(); + return m_pimpl->m_edge_mapper.find_input_edge(node, input); +} + +OutputEdge onnx_editor::ONNXModelEditor::find_output_edge(const EditorNode& node, + const EditorOutput& input) const +{ + update_mapper_if_needed(); + return m_pimpl->m_edge_mapper.find_output_edge(node, input); +} + +OutputEdge onnx_editor::ONNXModelEditor::find_output_edge(const std::string& output_name) const +{ + update_mapper_if_needed(); + return m_pimpl->m_edge_mapper.find_output_edge(output_name); +} + +std::vector + onnx_editor::ONNXModelEditor::find_output_consumers(const std::string& output_name) const +{ + update_mapper_if_needed(); + return m_pimpl->m_edge_mapper.find_output_consumers(output_name); +} + +bool onnx_editor::ONNXModelEditor::is_correct_and_unambiguous_node(const EditorNode& node) const +{ + update_mapper_if_needed(); + return m_pimpl->m_edge_mapper.is_correct_and_unambiguous_node(node); +} diff --git a/ngraph/test/models/onnx/model_editor/subgraph__inception_head.prototxt b/ngraph/test/models/onnx/model_editor/subgraph__inception_head.prototxt index f41a21428ab..1b024156b0e 100644 --- a/ngraph/test/models/onnx/model_editor/subgraph__inception_head.prototxt +++ b/ngraph/test/models/onnx/model_editor/subgraph__inception_head.prototxt @@ -8,7 +8,7 @@ graph { input: "conv1/7x7_s2_w_0" input: "conv1/7x7_s2_b_0" output: "conv1/7x7_s2_1" - name: "" + name: "conv1" op_type: "Conv" attribute { name: "strides" @@ -34,13 +34,13 @@ graph { node { input: "conv1/7x7_s2_1" output: "conv1/7x7_s2_2" - name: "" + name: "relu1" op_type: "Relu" } node { input: "conv1/7x7_s2_2" output: "pool1/3x3_s2_1" - name: "" + name: "maxpool1" op_type: "MaxPool" attribute { name: "strides" diff --git a/ngraph/test/models/onnx/model_editor/subgraph_extraction_tests.prototxt b/ngraph/test/models/onnx/model_editor/subgraph_extraction_tests.prototxt index 9e79acc9cf9..fe8972df10c 100644 --- a/ngraph/test/models/onnx/model_editor/subgraph_extraction_tests.prototxt +++ b/ngraph/test/models/onnx/model_editor/subgraph_extraction_tests.prototxt @@ -5,12 +5,14 @@ graph { input: "in1" output: "relu1" op_type: "Relu" + name: "relu1_name" } node { input: "relu1" input: "in2" output: "add1" op_type: "Add" + name: "add_ambiguous_name" } node { input: "in3" @@ -23,12 +25,14 @@ graph { input: "add1" output: "add2" op_type: "Add" + name: "add_ambiguous_name" } node { input: "add1" input: "conv1" output: "mul2" op_type: "Mul" + name: "" } node { input: "add2" @@ -40,6 +44,7 @@ graph { i: 1 type: INT } + name: "split_name" } node { input: "relu1" diff --git a/ngraph/test/models/onnx/model_editor/subgraph_extraction_tests_2.prototxt b/ngraph/test/models/onnx/model_editor/subgraph_extraction_tests_2.prototxt index 76d8587d9e8..a5fbee597db 100644 --- a/ngraph/test/models/onnx/model_editor/subgraph_extraction_tests_2.prototxt +++ b/ngraph/test/models/onnx/model_editor/subgraph_extraction_tests_2.prototxt @@ -5,6 +5,7 @@ graph { input: "in1" output: "relu1" op_type: "Relu" + name: "add1" } node { input: "in1" @@ -20,12 +21,14 @@ graph { input: "in2" output: "relu4" op_type: "Relu" + name: "relu4_name" } node { input: "relu1" input: "relu2" output: "add1" op_type: "Add" + name: "add1_name" } node { input: "relu2" diff --git a/ngraph/test/onnx/onnx_editor.cpp b/ngraph/test/onnx/onnx_editor.cpp index 84aa9333b3c..7dbe406166f 100644 --- a/ngraph/test/onnx/onnx_editor.cpp +++ b/ngraph/test/onnx/onnx_editor.cpp @@ -21,8 +21,7 @@ NGRAPH_SUPPRESS_DEPRECATED_START using namespace ngraph; -using namespace ngraph::onnx_import; -using namespace ngraph::onnx_editor; +using namespace onnx_editor; using namespace ngraph::test; static std::string s_manifest = "${MANIFEST}"; @@ -658,6 +657,478 @@ NGRAPH_TEST(onnx_editor, subgraph__inputs_getter) EXPECT_EQ(editor.model_inputs(), (std::vector{"conv1/7x7_s2_1"})); } +// HIGHT LEVEL API TESTS +// INPUT EDGES TEST +NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_output_name_and_input_name) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.prototxt")}; + + const InputEdge edge = editor.find_input_edge(EditorNode{EditorOutput{"conv1/7x7_s2_2"}}, + EditorInput{"conv1/7x7_s2_1"}); + EXPECT_EQ(edge.m_node_idx, 1); + EXPECT_EQ(edge.m_tensor_name, "conv1/7x7_s2_1"); + + const InputEdge edge2 = editor.find_input_edge(EditorNode{EditorOutput{"conv1/7x7_s2_1"}}, + EditorInput{"data_0"}); + EXPECT_EQ(edge2.m_node_idx, 0); + EXPECT_EQ(edge2.m_tensor_name, "data_0"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_output_name_and_input_index) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.prototxt")}; + + const InputEdge edge = + editor.find_input_edge(EditorNode{EditorOutput{"conv1/7x7_s2_2"}}, EditorInput{0}); + EXPECT_EQ(edge.m_node_idx, 1); + EXPECT_EQ(edge.m_tensor_name, "conv1/7x7_s2_1"); + + const InputEdge edge2 = + editor.find_input_edge(EditorNode{EditorOutput{"conv1/7x7_s2_1"}}, EditorInput{1}); + EXPECT_EQ(edge2.m_node_idx, 0); + EXPECT_EQ(edge2.m_tensor_name, "conv1/7x7_s2_w_0"); + + const InputEdge edge3 = + editor.find_input_edge(EditorNode{EditorOutput{"conv1/7x7_s2_1"}}, EditorInput{2}); + EXPECT_EQ(edge3.m_node_idx, 0); + EXPECT_EQ(edge3.m_tensor_name, "conv1/7x7_s2_b_0"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_name_and_input_name) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.prototxt")}; + + const InputEdge edge = + editor.find_input_edge(EditorNode{"relu1"}, EditorInput{"conv1/7x7_s2_1"}); + EXPECT_EQ(edge.m_node_idx, 1); + EXPECT_EQ(edge.m_tensor_name, "conv1/7x7_s2_1"); + + const InputEdge edge2 = + editor.find_input_edge(EditorNode{"conv1"}, EditorInput{"conv1/7x7_s2_w_0"}); + EXPECT_EQ(edge2.m_node_idx, 0); + EXPECT_EQ(edge2.m_tensor_name, "conv1/7x7_s2_w_0"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_name_and_input_index) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + const InputEdge edge = editor.find_input_edge(EditorNode{"relu1_name"}, EditorInput{0}); + EXPECT_EQ(edge.m_node_idx, 0); + EXPECT_EQ(edge.m_tensor_name, "in1"); + + const InputEdge edge2 = editor.find_input_edge(EditorNode{"split_name"}, EditorInput{0}); + EXPECT_EQ(edge2.m_node_idx, 5); + EXPECT_EQ(edge2.m_tensor_name, "add2"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_empty_node_name) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + try + { + const InputEdge edge = + editor.find_input_edge(EditorNode{""}, EditorInput{"conv1/7x7_s2_1"}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE( + msg.find("Node with name: not_given and output_name: not_given was not found") != + std::string::npos); + } +} + +// OUTPUT EDGES TEST +NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_output_name) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + const OutputEdge edge = + editor.find_output_edge(EditorNode{EditorOutput{"mul2"}}, EditorOutput{"mul2"}); + EXPECT_EQ(edge.m_node_idx, 4); + EXPECT_EQ(edge.m_tensor_name, "mul2"); + + const OutputEdge edge2 = + editor.find_output_edge(EditorNode{EditorOutput{"split1"}}, EditorOutput{"split2"}); + EXPECT_EQ(edge2.m_node_idx, 5); + EXPECT_EQ(edge2.m_tensor_name, "split2"); + + // simplified overload + const OutputEdge edge3 = + editor.find_output_edge("mul2"); + EXPECT_EQ(edge3.m_node_idx, 4); + EXPECT_EQ(edge3.m_tensor_name, "mul2"); + + const OutputEdge edge4 = + editor.find_output_edge("split2"); + EXPECT_EQ(edge4.m_node_idx, 5); + EXPECT_EQ(edge4.m_tensor_name, "split2"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_output_name_and_output_index) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + const OutputEdge edge = + editor.find_output_edge(EditorNode{EditorOutput{"add2"}}, EditorOutput{0}); + EXPECT_EQ(edge.m_node_idx, 3); + EXPECT_EQ(edge.m_tensor_name, "add2"); + + const OutputEdge edge2 = + editor.find_output_edge(EditorNode{EditorOutput{"split1"}}, EditorOutput{1}); + EXPECT_EQ(edge2.m_node_idx, 5); + EXPECT_EQ(edge2.m_tensor_name, "split2"); + + const OutputEdge edge3 = + editor.find_output_edge(EditorNode{EditorOutput{"split2"}}, EditorOutput{0}); + EXPECT_EQ(edge3.m_node_idx, 5); + EXPECT_EQ(edge3.m_tensor_name, "split1"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_node_name_and_output_name) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + const OutputEdge edge = + editor.find_output_edge(EditorNode{"relu1_name"}, EditorOutput{"relu1"}); + EXPECT_EQ(edge.m_node_idx, 0); + EXPECT_EQ(edge.m_tensor_name, "relu1"); + + const OutputEdge edge2 = + editor.find_output_edge(EditorNode{"split_name"}, EditorOutput{"split2"}); + EXPECT_EQ(edge2.m_node_idx, 5); + EXPECT_EQ(edge2.m_tensor_name, "split2"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_node_name_and_output_index) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + const OutputEdge edge = editor.find_output_edge(EditorNode{"relu1_name"}, EditorOutput{0}); + EXPECT_EQ(edge.m_node_idx, 0); + EXPECT_EQ(edge.m_tensor_name, "relu1"); + + const OutputEdge edge2 = editor.find_output_edge(EditorNode{"split_name"}, EditorOutput{1}); + EXPECT_EQ(edge2.m_node_idx, 5); + EXPECT_EQ(edge2.m_tensor_name, "split2"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_edge_const_network) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.prototxt")}; + + const InputEdge edge = + editor.find_input_edge(EditorNode{EditorOutput{"relu4"}}, EditorInput{0}); + EXPECT_EQ(edge.m_node_idx, 3); + EXPECT_EQ(edge.m_tensor_name, "in2"); + + const OutputEdge edge2 = editor.find_output_edge(EditorNode{"relu4_name"}, EditorOutput{0}); + EXPECT_EQ(edge2.m_node_idx, 3); + EXPECT_EQ(edge2.m_tensor_name, "relu4"); + + const OutputEdge edge3 = editor.find_output_edge(EditorNode{"add1_name"}, EditorOutput{0}); + EXPECT_EQ(edge3.m_node_idx, 4); + EXPECT_EQ(edge3.m_tensor_name, "add1"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_edge_error_handling) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.prototxt")}; + + // node with given output name not found + try + { + const InputEdge edge = + editor.find_input_edge(EditorNode{EditorOutput{"not_existed"}}, EditorInput{0}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE( + msg.find("Node with name: not_given and output_name: not_existed was not found") != + std::string::npos); + } + + // node with given name not found + try + { + const InputEdge edge = editor.find_input_edge(EditorNode{"not_existed"}, EditorInput{0}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE( + msg.find("Node with name: not_existed and output_name: not_given was not found") != + std::string::npos); + } + + // input index out of scope + try + { + const InputEdge edge = editor.find_input_edge(EditorNode{"relu4_name"}, EditorInput{1}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE(msg.find("Node with index: 3 has not input with index: 1") != + std::string::npos); + } + + // output index out of scope + try + { + const OutputEdge edge = + editor.find_output_edge(EditorNode{"relu4_name"}, EditorOutput{1}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE(msg.find("Node with index: 3 has not output with index: 1") != + std::string::npos); + } +} + +// Nodes with ambiguous node names tests +NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_but_matched_input) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + InputEdge edge = editor.find_input_edge(EditorNode{"add_ambiguous_name"}, EditorInput{"in2"}); + EXPECT_EQ(edge.m_node_idx, 1); + EXPECT_EQ(edge.m_tensor_name, "in2"); + + const InputEdge edge2 = editor.find_input_edge(EditorNode{"add_ambiguous_name"}, EditorInput{"add1"}); + EXPECT_EQ(edge2.m_node_idx, 3); + EXPECT_EQ(edge2.m_tensor_name, "add1"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_and_not_matched_input) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + try + { + const InputEdge edge = editor.find_input_edge(EditorNode{"add_ambiguous_name"}, EditorInput{"in3"}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE(msg.find("Input edge described by: add_ambiguous_name and input name: in3 was not found") != + std::string::npos); + } + + try + { + const InputEdge edge = editor.find_input_edge(EditorNode{"add_ambiguous_name"}, EditorInput{"relu1"}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE(msg.find("Given node name: add_ambiguous_name and input name: relu1 are ambiguous to determine input edge") != + std::string::npos); + } +} + +NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_and_input_index) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + try + { + const InputEdge edge = editor.find_input_edge(EditorNode{"add_ambiguous_name"}, EditorInput{0}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE(msg.find("Given node name: add_ambiguous_name and input index: 0 are ambiguous to determine input edge") != + std::string::npos); + } +} + +NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_but_matched_output) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + const OutputEdge edge = editor.find_output_edge(EditorNode{"add_ambiguous_name"}, EditorOutput{"add1"}); + EXPECT_EQ(edge.m_node_idx, 1); + EXPECT_EQ(edge.m_tensor_name, "add1"); + + const OutputEdge edge2 = editor.find_output_edge(EditorNode{"add_ambiguous_name"}, EditorOutput{"add2"}); + EXPECT_EQ(edge2.m_node_idx, 3); + EXPECT_EQ(edge2.m_tensor_name, "add2"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_the_same_node_name_and_output_name) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.prototxt")}; + + const OutputEdge edge = editor.find_output_edge(EditorNode{"add1"}, EditorOutput{0}); + EXPECT_EQ(edge.m_node_idx, 0); + EXPECT_EQ(edge.m_tensor_name, "relu1"); + + const OutputEdge edge2 = editor.find_output_edge(EditorNode{EditorOutput{"add1"}}, EditorOutput{0}); + EXPECT_EQ(edge2.m_node_idx, 4); + EXPECT_EQ(edge2.m_tensor_name, "add1"); +} + +NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_and_not_matched_output) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + try + { + const OutputEdge edge = editor.find_output_edge(EditorNode{"add_ambiguous_name"}, EditorOutput{"split2"}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE(msg.find("Output edge described by: add_ambiguous_name and output name: split2 was not found") != + std::string::npos); + } +} + +NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_and_output_index) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + try + { + const OutputEdge edge = editor.find_output_edge(EditorNode{"add_ambiguous_name"}, EditorOutput{0}); + } + catch (const std::exception& e) + { + std::string msg{e.what()}; + EXPECT_TRUE(msg.find("Given node name: add_ambiguous_name and output index: 0 are ambiguous to determine output edge") != + std::string::npos); + } +} + +NGRAPH_TEST(onnx_editor, editor_api_use_edge_mapper_with_graph_cutter) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + // InputEdge{1, "in2"} + const auto input_edge_1 = editor.find_input_edge( + EditorNode(EditorOutput("add1")), EditorInput(1)); + // InputEdge{2, "in3"} + const auto input_edge_2 = editor.find_input_edge( + EditorNode(EditorOutput("conv1")), EditorInput(0)); + + + const auto output_edge = editor.find_output_edge( + EditorNode(EditorOutput("mul2")), EditorOutput(0)); + // OutputEdge{4, "mul2"} + editor.cut_graph_fragment({input_edge_1, input_edge_2}, {output_edge}); + + const auto ref_model = + file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__existing_inputs_and_outputs_based_extraction.prototxt"); + + const auto result = compare_onnx_models(editor.model_string(), ref_model); + + EXPECT_TRUE(result.is_ok) << result.error_message; + + // check if mapper was updated after the model changed + const auto input_edge_4 = editor.find_input_edge( + EditorNode(EditorOutput("relu1")), EditorInput(0)); + EXPECT_EQ(input_edge_4.m_node_idx, 0); + EXPECT_EQ(input_edge_4.m_tensor_name, "in1"); + + const auto input_edge_5 = editor.find_input_edge( + EditorNode(EditorOutput("add1")), EditorInput(1)); + EXPECT_EQ(input_edge_5.m_node_idx, 1); + EXPECT_EQ(input_edge_5.m_tensor_name, "in2"); + + const auto output_edge_3 = editor.find_output_edge("mul2"); + EXPECT_EQ(output_edge_3.m_node_idx, 3); + EXPECT_EQ(output_edge_3.m_tensor_name, "mul2"); +} + +NGRAPH_TEST(onnx_editor, editor_api_find_output_consumers) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + std::vector output_consumers = editor.find_output_consumers("relu1"); + EXPECT_EQ(output_consumers.size(), 3); + EXPECT_EQ(output_consumers[0].m_node_idx, 1); + EXPECT_EQ(output_consumers[0].m_tensor_name, "relu1"); + EXPECT_EQ(output_consumers[1].m_node_idx, 3); + EXPECT_EQ(output_consumers[1].m_tensor_name, "relu1"); + EXPECT_EQ(output_consumers[2].m_node_idx, 6); + EXPECT_EQ(output_consumers[2].m_tensor_name, "relu1"); + + output_consumers = editor.find_output_consumers("add1"); + EXPECT_EQ(output_consumers.size(), 2); + EXPECT_EQ(output_consumers[0].m_node_idx, 3); + EXPECT_EQ(output_consumers[0].m_tensor_name, "add1"); + EXPECT_EQ(output_consumers[1].m_node_idx, 4); + EXPECT_EQ(output_consumers[1].m_tensor_name, "add1"); + + output_consumers = editor.find_output_consumers("in3"); + EXPECT_EQ(output_consumers.size(), 1); + EXPECT_EQ(output_consumers[0].m_node_idx, 2); + EXPECT_EQ(output_consumers[0].m_tensor_name, "in3"); +} + +NGRAPH_TEST(onnx_editor, editor_api_find_output_consumers_empty_result) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + const std::vector output_consumers = editor.find_output_consumers("not_existed"); + EXPECT_EQ(output_consumers.size(), 0); +} + +NGRAPH_TEST(onnx_editor, editor_api_is_correct_and_unambiguous_node) +{ + ONNXModelEditor editor{file_util::path_join( + SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.prototxt")}; + + bool is_correct_node = editor.is_correct_and_unambiguous_node(EditorNode{EditorOutput{"relu1"}}); + EXPECT_EQ(is_correct_node, true); + + is_correct_node = editor.is_correct_and_unambiguous_node(EditorNode{EditorOutput{"mul2"}}); + EXPECT_EQ(is_correct_node, true); + + is_correct_node = editor.is_correct_and_unambiguous_node(EditorNode{EditorOutput{"split2"}}); + EXPECT_EQ(is_correct_node, true); + + is_correct_node = editor.is_correct_and_unambiguous_node(EditorNode{"relu1_name"}); + EXPECT_EQ(is_correct_node, true); + + is_correct_node = editor.is_correct_and_unambiguous_node(EditorNode{EditorOutput{"in3"}}); + EXPECT_EQ(is_correct_node, false); + + is_correct_node = editor.is_correct_and_unambiguous_node(EditorNode{"add_ambiguous_name"}); + EXPECT_EQ(is_correct_node, false); + + is_correct_node = editor.is_correct_and_unambiguous_node(EditorNode{"not_exist"}); + EXPECT_EQ(is_correct_node, false); +} + using TestEngine = test::INTERPRETER_Engine; NGRAPH_TEST(onnx_editor, values__append_one_initializer) From 606d0f363a6867af9ce9f1c3479fed65984b1a26 Mon Sep 17 00:00:00 2001 From: Krzysztof Bruniecki Date: Mon, 17 May 2021 10:59:34 +0200 Subject: [PATCH 87/99] [GNA] Fix concat scale factors calculation (#5454) * [GNA] Fix concat scale factors calculation * Add tests with Input | Constant -> Strided Slices -> Concat Topology: Constant Parameter | | | | +---+ +---+ +---+ +---+ | | | | SS_1c ... SS_Nc SS_1p ... SS_Np | | | | | +----+ +----+ | | | | | +-------------+ | | +-------------+ \ | | / Concat Legend: SS == Strided Slice * Apply review Co-authored-by: Elizaveta Lobanova --- .../gna_plugin/frontend/scale_factor_calc.hpp | 1 + .../const_strided_slice_concat.cpp | 52 ++++++++++ .../const_strided_slice_concat.hpp | 14 +++ .../subgraph/const_strided_slice_concat.hpp | 39 ++++++++ .../subgraph/const_strided_slice_concat.cpp | 97 +++++++++++++++++++ 5 files changed, 203 insertions(+) create mode 100644 inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/const_strided_slice_concat.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/subgraph_tests/const_strided_slice_concat.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/subgraph/const_strided_slice_concat.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/src/subgraph/const_strided_slice_concat.cpp diff --git a/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp b/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp index be31c9fabd1..2f52f44a1e5 100644 --- a/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp +++ b/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp @@ -835,6 +835,7 @@ class ScaleFactorPerLayer { THROW_GNA_EXCEPTION << "Two Input layers " << (*sourceLayerIt)->name << " and " << (*nextInputIt)->name << " have different scales in concat!!! \n"; } + ++nextInputIt; } } diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/const_strided_slice_concat.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/const_strided_slice_concat.cpp new file mode 100644 index 00000000000..06fec972d17 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/const_strided_slice_concat.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "common_test_utils/test_constants.hpp" +#include "subgraph_tests/const_strided_slice_concat.hpp" + +using namespace SubgraphTestsDefinitions; + +namespace { +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; + +const std::vector> configs = { + { + {"GNA_DEVICE_MODE", "GNA_SW_FP32"} + }, + { + {"GNA_DEVICE_MODE", "GNA_SW_EXACT"} + } +}; + +std::vector inputChunksSizes = { + 32, 64 +}; +std::vector inputChunksNumber = { + 4, 7 +}; + +std::vector constChunksSizes = { + 96, 128 +}; +std::vector constChunksNumber = { + 1, 3 +}; + +INSTANTIATE_TEST_CASE_P(smoke_ConstStridedSliceConcatTest, ConstStridedSliceConcatTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_GNA), + ::testing::ValuesIn(configs), + ::testing::ValuesIn(inputChunksSizes), + ::testing::ValuesIn(inputChunksNumber), + ::testing::ValuesIn(constChunksSizes), + ::testing::ValuesIn(constChunksNumber)), + ConstStridedSliceConcatTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/const_strided_slice_concat.hpp b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/const_strided_slice_concat.hpp new file mode 100644 index 00000000000..9be3910b1d4 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/const_strided_slice_concat.hpp @@ -0,0 +1,14 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "shared_test_classes/subgraph/const_strided_slice_concat.hpp" + +namespace SubgraphTestsDefinitions { + +TEST_P(ConstStridedSliceConcatTest, CompareWithRefImpl) { + Run(); +}; +} // namespace SubgraphTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/subgraph/const_strided_slice_concat.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/subgraph/const_strided_slice_concat.hpp new file mode 100644 index 00000000000..cc24702e1cf --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/subgraph/const_strided_slice_concat.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include + +#include "shared_test_classes/base/layer_test_utils.hpp" +#include "ngraph_functions/builders.hpp" +#include "ngraph_functions/utils/ngraph_helpers.hpp" + +namespace SubgraphTestsDefinitions { + +typedef std::tuple< + InferenceEngine::Precision, // Network Precision + std::string, // Target Device + std::map, // Configuration + uint32_t, // Input chunk size + uint32_t, // Input chunk number + uint32_t, // Const chunk size + uint32_t // Const chunk number +> ConstStridedSliceConcatParams; + +class ConstStridedSliceConcatTest : public testing::WithParamInterface, + public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj); + InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo& info) const override; + +protected: + void SetUp() override; +}; + +} // namespace SubgraphTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/const_strided_slice_concat.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/const_strided_slice_concat.cpp new file mode 100644 index 00000000000..485aa72fce7 --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/const_strided_slice_concat.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/subgraph/const_strided_slice_concat.hpp" +#include "ngraph_functions/builders.hpp" + +namespace SubgraphTestsDefinitions { + +std::string ConstStridedSliceConcatTest::getTestCaseName(testing::TestParamInfo obj) { + InferenceEngine::Precision netPrecision; + std::string targetDevice; + std::map configuration; + uint32_t inputSliceSize; + uint32_t constSliceSize; + uint32_t inputSlices; + uint32_t constSlices; + std::tie(netPrecision, targetDevice, configuration, inputSliceSize, inputSlices, constSliceSize, constSlices) = obj.param; + + std::ostringstream result; + result << "ISS=" << inputSliceSize << "_"; + result << "ISN=" << inputSlices << "_"; + result << "CSS=" << constSliceSize << "_"; + result << "CSN=" << constSlices << "_"; + result << "netPRC=" << netPrecision.name() << "_"; + result << "targetDevice=" << targetDevice; + for (auto const& configItem : configuration) { + result << "_configItem=" << configItem.first << "_" << configItem.second; + } + return result.str(); +} + +InferenceEngine::Blob::Ptr ConstStridedSliceConcatTest::GenerateInput(const InferenceEngine::InputInfo& info) const { + InferenceEngine::Blob::Ptr blob = make_blob_with_precision(info.getTensorDesc()); + blob->allocate(); + + auto* rawBlobDataPtr = blob->buffer().as(); + std::vector values = CommonTestUtils::generate_float_numbers(blob->size(), -0.5f, 0.5f); + for (size_t i = 0; i < blob->size(); i++) { + rawBlobDataPtr[i] = values[i]; + } + return blob; +} + +namespace { +template +void appendSlices(A&& destVector, B&& src, const int64_t chunkSize, const int64_t totalSize, C precission) { + for (int64_t start = 0; start < totalSize; start += chunkSize) { + using ngraph::builder::makeStridedSlice; + destVector.push_back(makeStridedSlice(src, { 0, start }, { 0, start + chunkSize }, { 1, 1 }, precission, { 1, 0 }, { 1, 0 })); + } +} +} // namespace + +// Topology: +// +// Constant Parameter +// | | | | +// +---+ +---+ +---+ +---+ +// | | | | +// SS_1c ... SS_Nc SS_1p ... SS_Np +// | | | | +// | +----+ +----+ | +// | | | | +// +-------------+ | | +-------------+ +// \ | | / +// Concat +// +// Legend: +// SS == Strided Slice +void ConstStridedSliceConcatTest::SetUp() { + InferenceEngine::Precision netPrecision; + std::map tempConfig; + uint32_t inputSliceSize; + uint32_t constSliceSize; + uint32_t inputSlices; + uint32_t constSlices; + std::tie(netPrecision, targetDevice, tempConfig, inputSliceSize, inputSlices, constSliceSize, constSlices) = this->GetParam(); + configuration.insert(tempConfig.begin(), tempConfig.end()); + + std::vector inputShape; + const size_t totalInputSize = static_cast(inputSlices) * inputSliceSize; + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto params = ngraph::builder::makeParams(ngPrc, { std::vector{ 1, totalInputSize } }); + + const auto totalConstantSize = constSlices * constSliceSize; + auto constantValues = CommonTestUtils::generate_float_numbers(totalConstantSize, -0.2f, 0.2f); + auto constant = ngraph::builder::makeConstant(ngPrc, { 1, totalConstantSize }, constantValues); + + std::vector> allToConcat; + appendSlices(allToConcat, params[0], inputSliceSize, totalInputSize, ngPrc); + appendSlices(allToConcat, constant, constSliceSize, totalConstantSize, ngPrc); + auto concat = ngraph::builder::makeConcat(allToConcat, 1); + + function = std::make_shared(concat, params, "ConstStridedSliceConcatTest"); +} +} // namespace SubgraphTestsDefinitions From c1a38109c7ea7b0b2a4b54715c4d572b7fdc506d Mon Sep 17 00:00:00 2001 From: Mikhail Treskin Date: Mon, 17 May 2021 12:13:02 +0300 Subject: [PATCH 88/99] [SubgraphsDumper] Extract statistics instead of constants with weights. (#5149) * Store weights range in meta info instead of cloning whole constant * Add command line option for constants size serialization threshold * Update IR Runner to handle OP meta information * Fix interpolate type_prop tests * Skip new failures in SLT * Fix models count * Add dynamism elimination option. * TopK shape propagation changed * Fix type_prop tests for TopK --- .../conformance/subgraphs_dumper/README.md | 10 +- .../subgraphs_dumper/include/gflag_config.hpp | 23 +- .../include/matchers/base_matcher.hpp | 41 +-- .../include/matchers/convolutions.hpp | 22 ++ .../include/matchers/matchers_manager.hpp | 22 +- .../include/matchers/single_op.hpp | 31 ++- .../subgraphs_dumper/include/op_cloner.hpp | 7 +- .../subgraphs_dumper/include/ops_cache.hpp | 27 +- .../include/utils/dynamism_resolver.hpp | 13 + .../include/utils/model_wrap_struct.hpp | 31 +++ .../conformance/subgraphs_dumper/src/main.cpp | 77 ++++-- .../src/matchers/convolutions.cpp | 62 +++++ .../src/matchers/matchers_manager.cpp | 22 +- .../src/matchers/single_op.cpp | 65 +++-- .../subgraphs_dumper/src/op_cloner.cpp | 246 +++++++++++------- .../subgraphs_dumper/src/ops_cache.cpp | 189 ++++++++------ .../src/utils/dynamism_resolver.cpp | 82 ++++++ .../tests/matchers/convolutions_matcher.cpp | 84 ++++++ .../tests/matchers/generic_single_op.cpp | 15 +- .../skip_tests_config.cpp | 14 +- .../skip_tests_config.cpp | 2 + .../shared_test_classes/read_ir/read_ir.hpp | 2 + .../src/read_ir/read_ir.cpp | 76 ++++-- .../layer_test_utils/op_info.hpp | 34 +++ .../include/ngraph_functions/builders.hpp | 2 +- .../ngraph_functions/utils/data_utils.hpp | 76 ++++-- .../ngraph_functions/src/batch_norm.cpp | 6 +- .../ngraph_functions/src/fake_quantize.cpp | 8 +- .../ngraph_functions/src/gru_cell.cpp | 2 +- .../ngraph_functions/src/lstm_cell.cpp | 2 +- .../ngraph_functions/src/rnn_cell.cpp | 2 +- ngraph/core/src/op/interpolate.cpp | 2 +- ngraph/core/src/op/topk.cpp | 3 +- ngraph/test/type_prop/interpolate.cpp | 10 +- ngraph/test/type_prop/top_k.cpp | 4 +- 35 files changed, 976 insertions(+), 338 deletions(-) create mode 100644 inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/convolutions.hpp create mode 100644 inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/utils/dynamism_resolver.hpp create mode 100644 inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/utils/model_wrap_struct.hpp create mode 100644 inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/convolutions.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/utils/dynamism_resolver.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/tests/matchers/convolutions_matcher.cpp create mode 100644 inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/layer_test_utils/op_info.hpp diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/README.md b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/README.md index 0cddb328e34..1f21dd1c07f 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/README.md +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/README.md @@ -16,8 +16,14 @@ Outcome of a build is a `subgrpahsDumper` binary located in building artifacts f ## Running The tool takes two command line parameters: -* `--input_folders` - comma separated list for recursive search for models to analyse -* `--output_folder` - path to the output folder which will be used for extracted subgrpahs serialization in IR format +* `--input_folders` - Required. Comma separated paths to the input folders with IRs +* `--output_folder` - Required. Path to the output folders where to serialize IRs +* `--path_regex` - Optional. regular expression to be applied in input folders recursive discovery +* `--constants_size_threshold` - Optional. Maximum size of constant in megabytes to be serialized. + If constant size exceeds specified number it will be replaced + with parameter and meta information about original data range will be saved +* `--eliminate_dynamism` - Optional. If specified dynamic shapes will be eliminated from model + and replaced by propagated upper bound values (if possible) E.g. ```subgraphsDumper --input_folders /folder/with/models,/another/folder/with/models --output_folder /output/folder``` diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/gflag_config.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/gflag_config.hpp index 19a38e2d2ef..c37e45c445b 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/gflag_config.hpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/gflag_config.hpp @@ -9,11 +9,23 @@ static const char help_message[] = "Print a usage message."; static const char input_folders_message[] = "Required. Comma separated paths to the input folders with IRs"; -static const char output_folder_message[] = "Required. Path to the output folders with IRs"; +static const char output_folder_message[] = "Required. Path to the output folders where to serialize IRs"; +static const char path_regex_message[] = "Optional. regular expression to be applied in input " + "folders recursive discovery"; +static const char constants_size_threshold_message[] = "Optional. Maximum size of constant in megabytes" + " to be serialized.\n" + "If constant size exceeds specified number it will be replaced" + "with parameter and meta information about original data range " + "will be saved"; +static const char eliminate_dynamism_message[] = "Optional. If specified dynamic shapes will be eliminated from model" + "and replaced by propagated upper bound values (if possible)"; DEFINE_bool(h, false, help_message); DEFINE_string(input_folders, ".", input_folders_message); DEFINE_string(output_folder, "output", output_folder_message); +DEFINE_string(path_regex, ".*", output_folder_message); +DEFINE_double(constants_size_threshold, 1., constants_size_threshold_message); +DEFINE_bool(eliminate_dynamism, true, eliminate_dynamism_message); /** * @brief This function shows a help message @@ -23,8 +35,11 @@ static void showUsage() { std::cout << "Subgraph Dumper [OPTION]\n"; std::cout << "Options:\n"; std::cout << "\n"; - std::cout << " -h " << help_message << "\n"; - std::cout << " --input_folders \"\" " << input_folders_message << "\n"; - std::cout << " --output_folder \"\" " << output_folder_message << "\n"; + std::cout << " -h " << help_message << "\n"; + std::cout << " --input_folders \"\" " << input_folders_message << "\n"; + std::cout << " --output_folder \"\" " << output_folder_message << "\n"; + std::cout << " --path_regex \"\" " << path_regex_message << "\n"; + std::cout << " --constants_size_threshold \"\" " << constants_size_threshold_message << "\n"; + std::cout << " --eliminate_dynamism \"\" " << eliminate_dynamism_message << "\n"; std::cout << std::flush; } \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/base_matcher.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/base_matcher.hpp index 65db08f203d..bb75c373246 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/base_matcher.hpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/base_matcher.hpp @@ -9,6 +9,8 @@ #include "ngraph/node.hpp" #include "pugixml.hpp" +#include "functional_test_utils/include/functional_test_utils/layer_test_utils/op_info.hpp" + namespace SubgraphsDumper { class MatchersManager; @@ -20,19 +22,22 @@ public: explicit iMatcherConfig(bool is_fallback_config) : is_fallback_config(is_fallback_config) {} iMatcherConfig( - std::vector ignored_attributes, - std::vector ignored_ports, - bool _is_fallback_config) - : ignored_attributes(std::move(ignored_attributes)), - ignored_ports(std::move(ignored_ports)), - is_fallback_config(_is_fallback_config) {} + std::vector ignored_attributes, + std::vector ignored_ports, + bool is_fallback_config, + bool ignore_matching = false) + : ignored_attributes(std::move(ignored_attributes)), + ignored_ports(std::move(ignored_ports)), + is_fallback_config(is_fallback_config), + ignore_matching(ignore_matching) {} // Empty vectors stands for any of possible values std::vector ignored_attributes; std::vector ignored_ports; bool is_fallback_config; + bool ignore_matching = false; - virtual bool op_in_config(const std::shared_ptr& node) = 0; + virtual bool op_in_config(const std::shared_ptr &node) = 0; virtual ~iMatcherConfig() = default; }; @@ -42,9 +47,12 @@ struct MatcherConfig : public iMatcherConfig { public: MatcherConfig() : iMatcherConfig(sizeof...(OPTypes) == 0) {} - MatcherConfig(std::vector ignored_attributes, std::vector ignored_ports) - : iMatcherConfig( - std::move(ignored_attributes), std::move(ignored_ports), sizeof...(OPTypes) == 0) {} + MatcherConfig(std::vector ignored_attributes, std::vector ignored_ports, + bool ignore_matching = false) + : iMatcherConfig( + std::move(ignored_attributes), std::move(ignored_ports), sizeof...(OPTypes) == 0, ignore_matching) {} + + MatcherConfig(bool ignore_matching) : iMatcherConfig({}, {}, sizeof...(OPTypes) == 0, ignore_matching) {} bool op_in_config(const std::shared_ptr &node) override { std::initializer_list vals{(ngraph::is_type(node))...}; @@ -54,20 +62,23 @@ public: class Matcher { using Ptr = std::shared_ptr; + friend class MatchersManager; public: - virtual bool match(const std::shared_ptr& node, const std::shared_ptr& ref) const = 0; + virtual bool match(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const = 0; virtual ~Matcher() = default; protected: - virtual const char* get_name() = 0; + virtual void configure(const pugi::xml_document &cfg) = 0; - virtual void configure(const pugi::xml_document& cfg) = 0; - - iMatcherConfig::Ptr get_config(const std::shared_ptr& node) const; + iMatcherConfig::Ptr get_config(const std::shared_ptr &node) const; std::vector default_configs; + + virtual bool match_only_configured_ops() const = 0; // TODO: Add setter for external configuration purposes. }; } // namespace SubgraphsDumper diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/convolutions.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/convolutions.hpp new file mode 100644 index 00000000000..a877e9e2729 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/convolutions.hpp @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once +#include "matchers/single_op.hpp" +namespace SubgraphsDumper { +class ConvolutionsMatcher : public SingleOpMatcher { +public: + ConvolutionsMatcher(); + + bool match_inputs(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const override; + bool match(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const override; + +protected: + bool match_only_configured_ops() const override { return true; } +}; +} // namespace SubgraphsDumper \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/matchers_manager.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/matchers_manager.hpp index 852a15ccc46..0da92a0e1c5 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/matchers_manager.hpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/matchers_manager.hpp @@ -6,7 +6,8 @@ #include "pugixml.hpp" #include "ngraph/node.hpp" -#include "single_op.hpp" +#include "matchers/single_op.hpp" +#include "matchers/convolutions.hpp" namespace SubgraphsDumper { class Matcher; @@ -14,24 +15,31 @@ class Matcher; class MatchersManager { public: using RegistryMap = std::map>; - using MatchersMap = std::map; + using MatchersMap = std::map; explicit MatchersManager(const std::string &cfg_path = {}); - bool match_all(const std::shared_ptr &node, const std::shared_ptr &ref); + bool match_all(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info); - bool match_any(const std::shared_ptr &node, const std::shared_ptr &ref); + bool match_any(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info); // TODO: Implement default xml config file generation by Matchers void generate_config() {} private: - std::vector run_matchers(const std::shared_ptr &node, const std::shared_ptr &ref); + std::vector run_matchers(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info); // TODO: No copy constructor for xml_document // pugi::xml_document m_cfg; RegistryMap m_registry = { - {SingleOpMatcher::name, []() { return std::make_shared(); }} + {"generic_single_op", []() { return std::make_shared(); }}, + {"convolutions", []() { return std::make_shared(); }} }; MatchersMap m_matchers = {}; }; -} // namespace SubgraphsDumper +} // namespace SubgraphsDumper \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/single_op.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/single_op.hpp index cc31c0a31a3..a4d7e1bf697 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/single_op.hpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/matchers/single_op.hpp @@ -17,18 +17,29 @@ class SingleOpMatcher : public Matcher { public: SingleOpMatcher(); - bool match(const std::shared_ptr &node, const std::shared_ptr &ref) const override; + bool match(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const override; + bool same_op_type(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const; + + virtual bool match_inputs(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const; + bool match_outputs(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const; + bool same_attrs(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const; + bool match_ports(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const; - static const char *name; protected: - const char *get_name() override { return name; } - void configure(const pugi::xml_document &cfg) override {} -private: - bool same_op_type(const std::shared_ptr &node, const std::shared_ptr &ref) const; - bool match_inputs(const std::shared_ptr &node, const std::shared_ptr &ref) const; - bool match_outputs(const std::shared_ptr &node, const std::shared_ptr &ref) const; - bool same_attrs(const std::shared_ptr &node, const std::shared_ptr &ref) const; - bool match_ports(const std::shared_ptr &node, const std::shared_ptr &ref) const; + + bool match_only_configured_ops() const override { return false; } }; } // namespace SubgraphsDumper diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/op_cloner.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/op_cloner.hpp index 49e6032c1a8..67ecb04321d 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/op_cloner.hpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/op_cloner.hpp @@ -9,15 +9,16 @@ #include #include +#include "ops_cache.hpp" namespace SubgraphsDumper { struct ClonersMap { - using clone_fn = - std::function(const std::shared_ptr&)>; - + using clone_fn = std::function(const std::shared_ptr &, + LayerTestsUtils::OPInfo &meta)>; using cloners_map_type = std::map; + static float constant_size_threshold_mb; static const cloners_map_type cloners; }; diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/ops_cache.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/ops_cache.hpp index e4d11e888c9..356e3c1438e 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/ops_cache.hpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/ops_cache.hpp @@ -10,13 +10,14 @@ #include #include #include "matchers/matchers_manager.hpp" +#include "functional_test_utils/include/functional_test_utils/layer_test_utils/op_info.hpp" namespace SubgraphsDumper { class OPCache { public: OPCache() : num_neighbours_to_cache(0), manager(MatchersManager()), - m_ops_cache(std::vector, OPInfo>>()) {} + m_ops_cache(std::vector, LayerTestsUtils::OPInfo>>()) {} static std::unique_ptr make_cache() { return std::unique_ptr(new OPCache()); @@ -30,20 +31,20 @@ public: void set_num_neighbours_to_cache(size_t num) { num_neighbours_to_cache = num; } + void serialize_meta_info(const LayerTestsUtils::OPInfo &info, const std::string &path); + + float get_size_of_cached_ops(); + protected: - struct OPInfo { - std::string source_model; - std::map found_in_models; - - OPInfo(const std::string &_source_model) : source_model(_source_model) { - found_in_models = {{_source_model, 1}}; - } - - OPInfo() = default; - }; - - std::vector, OPInfo>> m_ops_cache; + std::vector, LayerTestsUtils::OPInfo>> m_ops_cache; MatchersManager manager; size_t num_neighbours_to_cache = 0; + enum SerializationStatus { + OK = 0, + FAILED = 1, + RETRY = 2, + }; + SerializationStatus serialize_function(const std::pair, LayerTestsUtils::OPInfo> &op_info, + const std::string &serialization_dir); }; } // namespace SubgraphsDumper diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/utils/dynamism_resolver.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/utils/dynamism_resolver.hpp new file mode 100644 index 00000000000..9e4db4faa74 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/utils/dynamism_resolver.hpp @@ -0,0 +1,13 @@ +// Copyright (C) 2019 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +namespace SubgraphsDumper { +// Copy from serialization transformation pass +void resolve_dynamic_shapes(const std::shared_ptr& f); + +} // namespace SubgraphsDumper \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/utils/model_wrap_struct.hpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/utils/model_wrap_struct.hpp new file mode 100644 index 00000000000..a4514451707 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/include/utils/model_wrap_struct.hpp @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +namespace SubgraphsDumper { +struct Model { + std::string xml; + std::string bin; + size_t size; + + Model(std::string model) { + xml = model; + bin = CommonTestUtils::replaceExt(model, "bin"); + if (CommonTestUtils::fileExists(bin)) { + size = CommonTestUtils::fileSize(bin); + } else { + size = 0; + } + } + + bool operator<(const Model &m) const { + return size < m.size; + } + + bool operator>(const Model &m) const { + return size > m.size; + } +}; +} // namespace SubgraphsDumper \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/main.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/main.cpp index 4d1f787f6ed..0bd42bf169d 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/main.cpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/main.cpp @@ -4,15 +4,21 @@ #include #include +#include +#include #include "inference_engine.hpp" #include "common_test_utils/file_utils.hpp" #include "ops_cache.hpp" +#include "op_cloner.hpp" +#include "utils/dynamism_resolver.hpp" +#include "utils/model_wrap_struct.hpp" #include "gflag_config.hpp" +#include +#include -// TODO: Poor exceptions handling int main(int argc, char *argv[]) { uint8_t ret_code = 0; @@ -21,10 +27,26 @@ int main(int argc, char *argv[]) { showUsage(); return 0; } + SubgraphsDumper::ClonersMap::constant_size_threshold_mb = FLAGS_constants_size_threshold; + std::vector input_folder_content; std::vector dirs = CommonTestUtils::splitStringByDelimiter(FLAGS_input_folders); - std::vector input_folder_content = - CommonTestUtils::getFileListByPatternRecursive(dirs, std::regex(R"(.*\.xml)")); - + for (const auto &dir : dirs) { + if (!CommonTestUtils::directoryExists(dir)) { + std::string msg = "Input directory (" + dir + ") doesn't not exist!"; + throw std::runtime_error(msg); + } + const auto content = CommonTestUtils::getFileListByPatternRecursive(dirs, std::regex(R"(.*\.xml)")); + input_folder_content.insert(input_folder_content.end(), content.begin(), content.end()); + } + std::vector models; + auto xml_regex = std::regex(FLAGS_path_regex); + for (const auto &file : input_folder_content) { + if (std::regex_match(file, xml_regex)) { + models.emplace_back(SubgraphsDumper::Model(file)); + } + } + std::sort(models.begin(), models.end()); + std::reverse(models.begin(), models.end()); if (!CommonTestUtils::directoryExists(FLAGS_output_folder)) { std::string msg = "Output directory (" + FLAGS_output_folder + ") doesn't not exist!"; throw std::runtime_error(msg); @@ -32,28 +54,45 @@ int main(int argc, char *argv[]) { auto ie = InferenceEngine::Core(); auto cache = SubgraphsDumper::OPCache::make_cache(); + time_t rawtime; + struct tm *timeinfo; + char buffer[20]; + size_t all_models = models.size(); + for (size_t i = 0; i < all_models; ++i) { + const auto model = models[i]; + if (CommonTestUtils::fileExists(model.xml)) { + try { + time(&rawtime); + timeinfo = localtime(&rawtime); // NOLINT no localtime_r in C++11 - for (const auto &file : input_folder_content) { - try { - if (CommonTestUtils::fileExists(file)) { - std::cout << "Processing model: " << file << std::endl; - std::string bin_file = CommonTestUtils::replaceExt(file, "bin"); - if (!CommonTestUtils::fileExists(bin_file)) { - std::cerr << "Corresponding .bin file for the model " << file << " doesn't exist" << std::endl; + strftime(buffer, 20, "%H:%M:%S", timeinfo); + std::cout << "[" << std::string(buffer) << "][" << i + 1 << "/" << all_models << "]Processing model: " + << model.xml << std::endl; + if (!CommonTestUtils::fileExists(model.bin)) { + std::cout << "Corresponding .bin file for the model " << model.bin << " doesn't exist" << std::endl; continue; } - InferenceEngine::CNNNetwork net = ie.ReadNetwork(file); + + InferenceEngine::CNNNetwork net = ie.ReadNetwork(model.xml, model.bin); auto function = net.getFunction(); - cache->update_ops_cache(function, file); + if (FLAGS_eliminate_dynamism) { + try { + SubgraphsDumper::resolve_dynamic_shapes(function); + } catch (std::exception &e) { + std::cout << "Failed to eliminate dynamism from model " << model.xml + << "\n Exception occurred:\n" << e.what() << "\nModel will be processed as is." + << std::endl; + } + } + cache->update_ops_cache(function, model.xml); + } catch (std::exception &e) { + std::cout << "Model processing failed with exception:" << std::endl << e.what() << std::endl; + ret_code = 1; + continue; } - } catch (std::exception &e) { - std::cerr << "Model processing failed with exception:" << std::endl << e.what() << std::endl; - ret_code = 1; - continue; } } - cache->serialize_cached_ops(FLAGS_output_folder); return ret_code; -} +} \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/convolutions.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/convolutions.cpp new file mode 100644 index 00000000000..ec6a8be9529 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/convolutions.cpp @@ -0,0 +1,62 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "matchers/convolutions.hpp" + +using namespace SubgraphsDumper; +ConvolutionsMatcher::ConvolutionsMatcher() { + default_configs = { + std::make_shared>(std::vector{}, std::vector{0, 1}) + }; +} + +bool ConvolutionsMatcher::match(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const { + const auto &cfg = get_config(node); + if (match_only_configured_ops() && cfg->is_fallback_config) { + return false; + } + if (cfg->ignore_matching) { + return false; + } + return same_op_type(node, ref, op_info) && + match_inputs(node, ref, op_info) && + match_outputs(node, ref, op_info) && + same_attrs(node, ref, op_info) && + match_ports(node, ref, op_info); +} +bool ConvolutionsMatcher::match_inputs(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const { + if (node->get_input_size() != ref->get_input_size()) { + return false; + } + bool rankIsEqual = node->get_input_tensor(0).get_partial_shape().rank() == + ref->get_input_tensor(0).get_partial_shape().rank(); + bool elemTypeIsEqual = node->get_input_tensor(0).get_element_type() == + ref->get_input_tensor(0).get_element_type(); + bool is_dynamic = node->get_input_node_ptr(0)->is_dynamic() == + ref->get_input_node_ptr(0)->is_dynamic(); + if (!(rankIsEqual && elemTypeIsEqual && is_dynamic)) { + return false; + } + bool has_groups = std::dynamic_pointer_cast(node) != nullptr || + std::dynamic_pointer_cast(node); + size_t kernel_size_offset = has_groups ? 3 : 2; + auto ref_weights_shape = ref->get_input_tensor(1).get_shape(); + auto cur_weights_shape = node->get_input_tensor(1).get_shape(); + const auto ref_kernel_size = std::vector(ref_weights_shape.begin() + kernel_size_offset, + ref_weights_shape.end()); + const auto cur_kernel_size = std::vector(cur_weights_shape.begin() + kernel_size_offset, + cur_weights_shape.end()); + if (ref_kernel_size != cur_kernel_size) { + return false; + } + return true; +} diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/matchers_manager.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/matchers_manager.cpp index edaca1230cd..8e0c7833f6f 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/matchers_manager.cpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/matchers_manager.cpp @@ -6,13 +6,19 @@ using namespace SubgraphsDumper; -bool MatchersManager::match_any(const std::shared_ptr &node, const std::shared_ptr &ref) { - const auto matches = this->run_matchers(node, ref); - return std::any_of(matches.begin(), matches.end(), [](bool i) { return i; }); +bool MatchersManager::match_any(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) { + for (const auto &it : m_matchers) { + if (it.second->match(node, ref, op_info)) return true; + } + return false; } -bool MatchersManager::match_all(const std::shared_ptr &node, const std::shared_ptr &ref) { - const auto matches = this->run_matchers(node, ref); +bool MatchersManager::match_all(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) { + const auto matches = this->run_matchers(node, ref, op_info); return std::all_of(matches.begin(), matches.end(), [](bool i) { return i; }); } @@ -25,10 +31,12 @@ MatchersManager::MatchersManager(const std::string &cfg_path) { } } -std::vector MatchersManager::run_matchers(const std::shared_ptr &node, const std::shared_ptr &ref) { +std::vector MatchersManager::run_matchers(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) { std::vector matches; for (const auto &it : m_matchers) { - matches.push_back(it.second->match(node, ref)); + matches.push_back(it.second->match(node, ref, op_info)); } return matches; } diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/single_op.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/single_op.cpp index 987744ca915..43d8dc9fdd7 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/single_op.cpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/matchers/single_op.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation + // Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // @@ -62,20 +62,21 @@ bool compare_constants_data(const std::shared_ptr &op, case ngraph::element::Type_t::u64: return compare_constants_data(op, ref); default: - std::cerr << "Can't compare constants" << op << " with " << ref << "\n" << "Unsupported data type"; + std::cout << "Can't compare constants" << op << " with " << ref << "\n" << "Unsupported data type"; return false; } } -const char *SingleOpMatcher::name = "generic_single_op"; -bool -SingleOpMatcher::same_op_type(const std::shared_ptr &node, const std::shared_ptr &ref) const { +bool SingleOpMatcher::same_op_type(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const { return node->get_type_info().name == ref->get_type_info().name && node->get_type_info().version == ref->get_type_info().version; } -bool -SingleOpMatcher::match_inputs(const std::shared_ptr &node, const std::shared_ptr &ref) const { +bool SingleOpMatcher::match_inputs(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const { if (node->get_input_size() != ref->get_input_size()) { return false; } @@ -95,7 +96,9 @@ SingleOpMatcher::match_inputs(const std::shared_ptr &node, const s } bool -SingleOpMatcher::match_outputs(const std::shared_ptr &node, const std::shared_ptr &ref) const { +SingleOpMatcher::match_outputs(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const { if (node->get_output_size() != ref->get_output_size()) { return false; } @@ -110,16 +113,20 @@ SingleOpMatcher::match_outputs(const std::shared_ptr &node, const return true; } -bool SingleOpMatcher::same_attrs(const std::shared_ptr &node, const std::shared_ptr &ref) const { +bool SingleOpMatcher::same_attrs(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const { return attributes::compare(node.get(), ref.get(), Comparator::CmpValues::ATTRIBUTES).valid; } -bool SingleOpMatcher::match_ports(const std::shared_ptr &node, const std::shared_ptr &ref) const { +bool SingleOpMatcher::match_ports(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const { const auto &cfg = get_config(node); const std::vector &ignored_ports = cfg->ignored_ports; for (size_t port_id = 0; port_id < node->get_input_size(); ++port_id) { - if (std::any_of(begin(ignored_ports), end(ignored_ports), [=](size_t p){return p == port_id;})) { + if (std::any_of(begin(ignored_ports), end(ignored_ports), [=](size_t p) { return p == port_id; })) { continue; } const auto &cur_node_input = node->input_value(port_id); @@ -132,19 +139,29 @@ bool SingleOpMatcher::match_ports(const std::shared_ptr &node, con if (cur_const_input && ref_const_input && !compare_constants_data(cur_const_input, ref_const_input)) { return false; - // Check that input nodes on the port both not constants + // Check that input nodes on the port both not constants } else if ((cur_const_input && !ref_const_input) || (!cur_const_input && ref_const_input)) { return false; } } return true; } -bool SingleOpMatcher::match(const std::shared_ptr &node, const std::shared_ptr &ref) const { - return same_op_type(node, ref) && - match_inputs(node, ref) && - match_outputs(node, ref) && - same_attrs(node, ref) && - match_ports(node, ref); + +bool SingleOpMatcher::match(const std::shared_ptr &node, + const std::shared_ptr &ref, + const LayerTestsUtils::OPInfo &op_info) const { + const auto &cfg = get_config(node); + if (match_only_configured_ops() && cfg->is_fallback_config) { + return false; + } + if (cfg->ignore_matching) { + return false; + } + return same_op_type(node, ref, op_info) && + match_inputs(node, ref, op_info) && + match_outputs(node, ref, op_info) && + same_attrs(node, ref, op_info) && + match_ports(node, ref, op_info); } SingleOpMatcher::SingleOpMatcher() { @@ -153,14 +170,16 @@ SingleOpMatcher::SingleOpMatcher() { std::make_shared>(std::vector{}, std::vector{0, 1, 2, 3, 4}), std::make_shared>(std::vector{}, std::vector{0, 1}), + + std::make_shared>(true) }; -} +} \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/op_cloner.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/op_cloner.cpp index 703c73a8b66..222e6dd1cb6 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/op_cloner.cpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/op_cloner.cpp @@ -1,141 +1,211 @@ // Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // - +#include #include "op_cloner.hpp" #include "ngraph/opsets/opset6.hpp" #include "common_test_utils/data_utils.hpp" namespace SubgraphsDumper { namespace { -const std::shared_ptr clone(const std::shared_ptr &node) { + + +template +void get_port_range(const std::shared_ptr &const_node, LayerTestsUtils::PortInfo &port_info) { + std::vector data = const_node->cast_vector(); + if (!data.empty()) { + auto min_max = std::minmax_element(data.begin(), data.end()); + port_info.min = *min_max.first; + port_info.max = *min_max.second; + } +} + + +void get_port_range(const std::shared_ptr &constant_input, LayerTestsUtils::PortInfo &port_info) { + switch (constant_input->get_element_type()) { + case ngraph::element::Type_t::boolean: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::bf16: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::f16: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::f32: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::f64: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::i8: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::i16: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::i32: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::i64: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::u1: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::u8: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::u16: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::u32: + get_port_range(constant_input, port_info); + break; + case ngraph::element::Type_t::u64: + get_port_range(constant_input, port_info); + break; + default: + break; + } +} + +std::shared_ptr clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { ngraph::OutputVector op_inputs; - for (const auto &input : node->inputs()) { - if (ngraph::op::is_constant(input.get_source_output().get_node_shared_ptr())) { - op_inputs.push_back(input.get_source_output().get_node_shared_ptr()->clone_with_new_inputs({})); + bool static_inputs = true; + for (size_t i = 0; i < node->get_input_size(); ++i) { + const auto input = node->input(i).get_source_output(); + static_inputs &= input.get_partial_shape().is_static(); + auto port_info = LayerTestsUtils::PortInfo(); + const auto constant = ngraph::get_constant_from_source(input); + if (constant != nullptr) { + get_port_range(constant, port_info); + float weights_size = + static_cast(ngraph::shape_size(constant->get_shape()) * + constant->get_element_type().size()) / (1024 * 1024); + if (weights_size > ClonersMap::constant_size_threshold_mb) { + std::cout << "Constant with size " << weights_size << " detected on port " << i << " of OP " << node + << std::endl + << "The constant will be replaced with parameter and initial data ranges meta info" + << std::endl; + auto param = std::make_shared(constant->get_element_type(), + constant->get_shape()); + op_inputs.push_back(param); + + } else { + const auto clone = std::make_shared(constant->get_element_type(), + constant->get_shape(), + constant->get_data_ptr()); + op_inputs.push_back(clone); + } } else { - op_inputs.push_back(std::make_shared(input.get_element_type(), - input.get_source_output().get_shape())); + auto param = std::make_shared(input.get_element_type(), + input.get_partial_shape()); + op_inputs.push_back(param); } + meta.ports_info[i] = port_info; } auto op_clone = node->clone_with_new_inputs(op_inputs); return op_clone; } -template -std::shared_ptr -copy_constant_with_randomization(const std::shared_ptr &const_node) { - std::vector data = const_node->cast_vector(); - if (!data.empty()) { - auto min_max = std::minmax_element(data.begin(), data.end()); - // Apply randomization only if constant stores several non-equal values - if (ngraph::shape_size(const_node->get_shape()) != 1 && - *min_max.first - *min_max.second > std::numeric_limits::epsilon()) { - CommonTestUtils::fill_vector(data, *min_max.first, *min_max.second); - } - } - return std::make_shared(const_node->get_element_type(), const_node->get_shape(), data); -} - - -std::shared_ptr -copy_constant_with_randomization(const std::shared_ptr &node, - const std::shared_ptr &constant_input) { - switch (node->get_element_type()) { - case ngraph::element::Type_t::boolean: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::bf16: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::f16: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::f32: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::f64: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::i8: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::i16: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::i32: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::i64: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::u1: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::u8: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::u16: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::u32: - return copy_constant_with_randomization(constant_input); - case ngraph::element::Type_t::u64: - return copy_constant_with_randomization(constant_input); - default: - return {}; - } -} - std::shared_ptr clone_weightable_node(const std::shared_ptr &node, - const std::vector &weight_ports) { + const std::vector &weight_ports, + LayerTestsUtils::OPInfo &meta) { ngraph::OutputVector op_inputs; for (size_t i = 0; i < node->get_input_size(); ++i) { - const auto input = node->input(i).get_source_output().get_node_shared_ptr(); - const auto constant_input = std::dynamic_pointer_cast(input); + const auto input = node->input(i).get_source_output(); + const auto constant_input = ngraph::get_constant_from_source(input); + auto port_info = LayerTestsUtils::PortInfo(); + // Input is Parameter or dynamic data pass if (!constant_input) { - op_inputs.push_back(std::make_shared(node->get_input_tensor(i).get_element_type(), - node->get_input_tensor(i).get_shape())); + auto param = std::make_shared(input.get_element_type(), + input.get_partial_shape()); + op_inputs.push_back(param); + meta.ports_info[i] = port_info; continue; } + get_port_range(constant_input, port_info); + // Input is Constant but not in the target weight ports if (std::find(weight_ports.begin(), weight_ports.end(), i) == weight_ports.end()) { - op_inputs.push_back(input->clone_with_new_inputs({})); + float weights_size = + static_cast(ngraph::shape_size(constant_input->get_shape()) * + constant_input->get_element_type().size()) / (1024 * 1024); + if (weights_size > ClonersMap::constant_size_threshold_mb) { + std::cout << "Constant with size " << weights_size << " detected on port " << i << " of OP " << node + << std::endl + << "The constant will be replaced with parameter and initial data ranges meta info" + << std::endl; + auto param = std::make_shared(constant_input->get_element_type(), + constant_input->get_shape()); + op_inputs.push_back(param); + } else { + const auto clone = std::make_shared(constant_input->get_element_type(), + constant_input->get_shape(), + constant_input->get_data_ptr()); + op_inputs.push_back(clone); + } + meta.ports_info[i] = port_info; continue; } - op_inputs.push_back(copy_constant_with_randomization(node, constant_input)); + // Input is constant and in the target weights ports + auto param = std::make_shared(constant_input->get_element_type(), + constant_input->get_shape()); + port_info.convert_to_const = true; + meta.ports_info[i] = port_info; + op_inputs.push_back(param); } auto op_clone = node->clone_with_new_inputs(op_inputs); return op_clone; } // Clone nodes requiring weights randomization -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr +clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {1}, meta); } -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr +clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {1}, meta); } -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr +clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {1}, meta); } -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr +clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {1}, meta); } -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr +clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {0, 1}, meta); } -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {0, 1}, meta); } -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr +clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {0, 1}, meta); } -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr +clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {0, 1}, meta); } -const std::shared_ptr clone(const std::shared_ptr &node) { - return clone_weightable_node(node, {1}); +std::shared_ptr clone(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone_weightable_node(node, {0, 1}, meta); } template -const std::shared_ptr clone_node(const std::shared_ptr &node) { - return clone(ngraph::as_type_ptr(node)); +std::shared_ptr clone_node(const std::shared_ptr &node, LayerTestsUtils::OPInfo &meta) { + return clone(ngraph::as_type_ptr(node), meta); } } // namespace @@ -148,7 +218,9 @@ const ClonersMap::cloners_map_type ClonersMap::cloners{ #include #include #include +#include }; #undef NGRAPH_OP +float ClonersMap::constant_size_threshold_mb = 0.5; } // namespace SubgraphsDumper diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/ops_cache.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/ops_cache.cpp index 41e276e10f9..2981709e5a2 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/ops_cache.cpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/ops_cache.cpp @@ -8,16 +8,16 @@ #include #include "inference_engine.hpp" #include "common_test_utils/file_utils.hpp" +#include "pugixml.hpp" using namespace SubgraphsDumper; - void OPCache::update_ops_cache(const std::shared_ptr &op, const std::string &source_model) { const bool op_found = [&] { for (auto &&it : m_ops_cache) { - if (manager.match_any(it.first, op)) { + if (manager.match_any(it.first, op, it.second)) { it.second.found_in_models[source_model] += 1; return true; } @@ -25,14 +25,20 @@ void OPCache::update_ops_cache(const std::shared_ptr &op, return false; }(); if (!op_found) { - // TODO: Extend for subgraphs caching - const auto& clone_fn = SubgraphsDumper::ClonersMap::cloners.at(op->get_type_info()); - m_ops_cache.emplace_back(clone_fn(op), OPInfo(source_model)); + const auto &clone_fn = SubgraphsDumper::ClonersMap::cloners.at(op->get_type_info()); + LayerTestsUtils::OPInfo meta(source_model); + try { + const std::shared_ptr op_clone = clone_fn(op, meta); + op_clone->set_friendly_name(op_clone->get_friendly_name() + "_cached"); + m_ops_cache.emplace_back(std::make_pair(op_clone, meta)); + } catch (std::exception &e) { + std::cout << e.what() << std::endl; + } } } void OPCache::update_ops_cache(const std::shared_ptr &func, const std::string &source_model) { - func->validate_nodes_and_infer_types(); + size_t cached_ops_count = m_ops_cache.size(); for (const auto &op : func->get_ordered_ops()) { if (ngraph::is_type(op) || ngraph::is_type(op) || @@ -41,6 +47,7 @@ void OPCache::update_ops_cache(const std::shared_ptr &func, co } update_ops_cache(op, source_model); } + std::cout << "\t" << m_ops_cache.size() - cached_ops_count << " new OPs were cached." << std::endl; } void OPCache::serialize_cached_ops(const std::string &serialization_dir) { @@ -48,77 +55,111 @@ void OPCache::serialize_cached_ops(const std::string &serialization_dir) { CommonTestUtils::createDirectoryRecursive(serialization_dir); } for (const auto &op : m_ops_cache) { - try { - auto rt_info = op.first->get_rt_info(); - std::cout << "Serializing function wrapping op " << op.first << std::endl; - if (rt_info.find("source_model") != rt_info.end()) { - auto val = rt_info["source_model"]; - auto source_model = std::dynamic_pointer_cast>(val); - if (source_model != nullptr) { - std::cout << " Taken from model: " << source_model->get() << std::endl; - } - } - - ngraph::ParameterVector params; - for (size_t i = 0; i < op.first->get_input_size(); ++i) { - if (ngraph::op::is_parameter(op.first->get_input_node_ptr(i))) { - auto param = std::dynamic_pointer_cast( - op.first->get_input_node_shared_ptr(i)); - params.push_back(param); - } - } - ngraph::ResultVector results; - for (auto &out : op.first->outputs()) { - results.push_back(std::make_shared(out)); - } - auto function = std::make_shared(results, params); - - bool output_shape_is_dynamic = false; - // TODO: Check 'o.get_partial_shape().is_static()' failed at - // inference-engine/src/transformations/src/transformations/serialize.cpp:680: - for (size_t i = 0; i < function->get_output_size(); ++i) { - if (function->get_output_partial_shape(i).is_dynamic()) { - std::cerr << "Can't serialize function related to op: " << std::endl << op.first << std::endl << - "Output shape on port " << i << " is dynamic" << std::endl; - output_shape_is_dynamic = true; + auto res = serialize_function(op, serialization_dir); + if (res != OPCache::SerializationStatus::RETRY) { + continue; + } else { + for (size_t i = 1; i <= 5; ++i) { + std::cout << "Serialization retry #" << i << std::endl; + res = serialize_function(op, serialization_dir); + if (res != OPCache::SerializationStatus::RETRY) { break; } } - if (output_shape_is_dynamic) { - continue; - } - function->validate_nodes_and_infer_types(); - // TODO: How to define element type for multi-output ops - auto op_el_type = op.first->get_output_element_type(0).get_type_name(); - auto current_op_folder = serialization_dir + CommonTestUtils::FileSeparator + - op.first->get_type_info().name + CommonTestUtils::FileSeparator + op_el_type; - std::cout << current_op_folder << std::endl; - if (!CommonTestUtils::directoryExists(current_op_folder)) { - CommonTestUtils::createDirectoryRecursive(current_op_folder); - } - auto op_name = op.first->get_name(); - std::replace(op_name.begin(), op_name.end(), '/', '_'); - std::replace(op_name.begin(), op_name.end(), '\\', '_'); - // TODO: Possible names collision - auto xml_path = current_op_folder + CommonTestUtils::FileSeparator + op_name + ".xml"; - auto bin_path = current_op_folder + CommonTestUtils::FileSeparator + op_name + ".bin"; - auto mapping = current_op_folder + CommonTestUtils::FileSeparator + op_name + ".csv"; - auto cnn_net = InferenceEngine::CNNNetwork(function); - cnn_net.serialize(xml_path, bin_path); - - std::string delimiter = ","; - std::ofstream out(mapping); - out << "Model" << delimiter << "counters\n"; - // TODO: rethink format of mapping - - // how to store both initial source model and usage statistics in one file? - out << op.second.source_model << delimiter << "source\n"; - for (const auto &m : op.second.found_in_models) { - out << m.first << delimiter << m.second << "\n"; - } - out.close(); - } catch (std::exception &e) { - std::cerr << "Failed to serialize function related to op" << op.first << std::endl - << "Exception occurred: " << e.what() << std::endl; } } } + +void OPCache::serialize_meta_info(const LayerTestsUtils::OPInfo &info, const std::string &path) { + pugi::xml_document doc; + pugi::xml_node root = doc.append_child("meta_info"); + pugi::xml_node models = root.append_child("models"); + models.append_child("initial_model").append_attribute("name").set_value(info.source_model.c_str()); + for (const auto &model : info.found_in_models) { + pugi::xml_node model_node = models.append_child("model"); + model_node.append_attribute("name").set_value(model.first.c_str()); + model_node.append_attribute("count").set_value(model.second); + } + auto ports_info = root.append_child("ports_info"); + for (const auto &port : info.ports_info) { + auto port_node = ports_info.append_child("port"); + port_node.append_attribute("id").set_value(port.first); + if (port.second.min == std::numeric_limits::min()) { + port_node.append_attribute("max").set_value("undefined"); + port_node.append_attribute("min").set_value("undefined"); + } else { + port_node.append_attribute("max").set_value(port.second.max); + port_node.append_attribute("min").set_value(port.second.min); + } + port_node.append_attribute("convert_to_const").set_value(port.second.convert_to_const); + } + doc.save_file(path.c_str()); +} + +float OPCache::get_size_of_cached_ops() { + float size = 0; + for (const auto &op : m_ops_cache) { + for (size_t i = 0; i < op.first->get_input_size(); ++i) { + const auto constant = std::dynamic_pointer_cast( + op.first->get_input_node_shared_ptr(i)); + if (constant != nullptr) { + size += static_cast(ngraph::shape_size(constant->get_shape()) * + constant->get_element_type().size()) / (1024 * 1024); + } + } + } + return size; +} + +OPCache::SerializationStatus +OPCache::serialize_function(const std::pair, LayerTestsUtils::OPInfo> &op, + const std::string &serialization_dir) { + try { + if (op.first->get_friendly_name() == "Relu_8793_cached") { + std::cout << std::endl; + } + std::cout << "Serializing function wrapping op " << op.first << std::endl; + std::cout << "Taken from model: " << op.second.source_model << std::endl; + + ngraph::ParameterVector params; + for (size_t i = 0; i < op.first->get_input_size(); ++i) { + if (ngraph::op::is_parameter(op.first->get_input_node_ptr(i))) { + auto param = std::dynamic_pointer_cast( + op.first->get_input_node_shared_ptr(i)); + params.push_back(param); + } + } + ngraph::ResultVector results; + for (auto &out : op.first->outputs()) { + results.push_back(std::make_shared(out)); + } + auto function = std::make_shared(results, params); + + // TODO: How to define element type for multi-output ops + auto op_el_type = op.first->get_output_element_type(0).get_type_name(); + auto current_op_folder = serialization_dir + CommonTestUtils::FileSeparator + + op.first->get_type_info().name + CommonTestUtils::FileSeparator + op_el_type; + std::cout << current_op_folder << std::endl; + if (!CommonTestUtils::directoryExists(current_op_folder)) { + CommonTestUtils::createDirectoryRecursive(current_op_folder); + } + auto op_name = op.first->get_name(); + std::replace(op_name.begin(), op_name.end(), '/', '_'); + std::replace(op_name.begin(), op_name.end(), '\\', '_'); + // TODO: Possible names collision + auto xml_path = current_op_folder + CommonTestUtils::FileSeparator + op_name + ".xml"; + auto bin_path = current_op_folder + CommonTestUtils::FileSeparator + op_name + ".bin"; + auto meta_info = current_op_folder + CommonTestUtils::FileSeparator + op_name + ".meta"; + auto cnn_net = InferenceEngine::CNNNetwork(function); + cnn_net.serialize(xml_path, bin_path); + serialize_meta_info(op.second, meta_info); + return OPCache::SerializationStatus::OK; + } catch (std::exception &e) { + std::cout << "Failed to serialize function related to op" << op.first << std::endl + << "Exception occurred: " << e.what() << std::endl; + if (std::string(e.what()).find("Can't open") != std::string::npos) { + return OPCache::SerializationStatus::RETRY; + } + return OPCache::SerializationStatus::FAILED; + } +} diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/utils/dynamism_resolver.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/utils/dynamism_resolver.cpp new file mode 100644 index 00000000000..6ecf8be2706 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/utils/dynamism_resolver.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "utils/dynamism_resolver.hpp" + +namespace SubgraphsDumper { + +bool has_dynamic_output(std::shared_ptr n) { + for (size_t i = 0; i < n->get_output_size(); i++) { + if (n->get_output_partial_shape(i).is_dynamic()) { + return true; + } + } + return false; +} + +void resolve_dynamic_shapes(const std::shared_ptr& f) { + const auto & f_ops = f->get_ordered_ops(); + if (std::all_of(f_ops.begin(), f_ops.end(), + [](std::shared_ptr results) { + return !results->is_dynamic() && !has_dynamic_output(results); })) { + return; + } + auto f_clone = ngraph::clone_function(*f); + const auto & f_clone_ops = f_clone->get_ordered_ops(); + NGRAPH_CHECK(f_ops.size() == f_clone_ops.size(), "Unexpected get_ordered_ops method behaviour"); + + for (size_t id = 0; id < f_ops.size(); ++id) { + auto & op = f_ops[id]; + auto & clone_op = f_clone_ops[id]; + + if (auto op_subgraph = std::dynamic_pointer_cast(op)) { + resolve_dynamic_shapes(op_subgraph->get_function()); + } + + op->validate_and_infer_types(); + clone_op->validate_and_infer_types(); + + // dynamic_to_static function converts dynamic dimensions to static using + // upperbound (get_max_length) dimension value. + auto dynamic_to_static = [&op](const ngraph::PartialShape & shape) -> ngraph::PartialShape { + if (shape.is_static() || shape.rank().is_dynamic()) { + return shape; + } + std::vector out_shape; + std::transform(std::begin(shape), std::end(shape), + std::back_inserter(out_shape), + [](const ngraph::Dimension& d) -> ngraph::Dimension { + return d.get_max_length(); + }); + NGRAPH_CHECK(ngraph::PartialShape(out_shape).is_static(), + "Dynamic dimension cannot be resolved in ", op); + return out_shape; + }; + + ngraph::OutputVector replacements(clone_op->get_output_size()); + if (!clone_op->constant_fold(replacements, clone_op->input_values())) { + for (size_t output_id = 0; output_id < clone_op->get_output_size(); ++output_id) { + clone_op->set_output_type(output_id, clone_op->output(output_id).get_element_type(), + dynamic_to_static(clone_op->output(output_id).get_partial_shape())); + op->set_output_type(output_id, clone_op->output(output_id).get_element_type(), + clone_op->output(output_id).get_partial_shape()); + } + } else { + for (size_t output_id = 0; output_id < clone_op->get_output_size(); ++output_id) { + op->set_output_type(output_id, replacements[output_id].get_element_type(), + replacements[output_id].get_partial_shape()); + } + + for (size_t i = 0; i < replacements.size(); ++i) { + auto node_output = clone_op->output(i); + auto replacement = replacements.at(i); + if (replacement.get_node_shared_ptr() && (node_output != replacement)) { + node_output.replace(replacement); + } + } + } + } +} + +} // namespace SubgraphsDumper \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/tests/matchers/convolutions_matcher.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/tests/matchers/convolutions_matcher.cpp new file mode 100644 index 00000000000..c06cbd89d27 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/tests/matchers/convolutions_matcher.cpp @@ -0,0 +1,84 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "matchers/convolutions.hpp" +#include "ngraph/ops.hpp" +#include "functional_test_utils/include/functional_test_utils/layer_test_utils/op_info.hpp" + +using namespace ngraph::op; +using namespace ngraph; +using ngraph::element::Type_t; + +class ConvolutionMatcherTest : public ::testing::Test { +protected: + void SetUp() { + matcher = SubgraphsDumper::ConvolutionsMatcher(); + op_info = LayerTestsUtils::OPInfo(); + } + + SubgraphsDumper::ConvolutionsMatcher matcher; + LayerTestsUtils::OPInfo op_info; +}; + + +// Check that two convolutions with different input shapes but same kernel size are match each other +TEST_F(ConvolutionMatcherTest, ConvsSameKernelSize) { + const auto param = std::make_shared(Type_t::f32, Shape({1, 3, 10, 10})); + const auto weights = std::make_shared(Type_t::f32, Shape({10, 3, 3, 3}), 1); + const auto op1 = std::make_shared(param, weights, Strides(0, 0), CoordinateDiff(0, 0), + CoordinateDiff(0, 0), Strides(0, 0)); + + const auto param2 = std::make_shared(Type_t::f32, Shape({1, 5, 20, 20})); + const auto weights2 = std::make_shared(Type_t::f32, Shape({10, 5, 3, 3}), 1); + const auto op2 = std::make_shared(param2, weights2, Strides(0, 0), CoordinateDiff(0, 0), + CoordinateDiff(0, 0), Strides(0, 0)); + ASSERT_TRUE(matcher.match(op1, op2, op_info)); +} + +// Check that two convolutions with different input shapes but same kernel size are match each other +TEST_F(ConvolutionMatcherTest, ConvsDifferentKernelSize) { + const auto param = std::make_shared(Type_t::f32, Shape({1, 3, 10, 10})); + const auto weights = std::make_shared(Type_t::f32, Shape({10, 3, 3, 5}), 1); + const auto op1 = std::make_shared(param, weights, Strides(0, 0), CoordinateDiff(0, 0), + CoordinateDiff(0, 0), Strides(0, 0)); + + const auto param2 = std::make_shared(Type_t::f32, Shape({1, 5, 20, 20})); + const auto weights2 = std::make_shared(Type_t::f32, Shape({10, 5, 3, 3}), 1); + const auto op2 = std::make_shared(param2, weights2, Strides(0, 0), CoordinateDiff(0, 0), + CoordinateDiff(0, 0), Strides(0, 0)); + ASSERT_FALSE(matcher.match(op1, op2, op_info)); +} + +// Check that two group convolutions with different input shapes but same kernel size are match each other +TEST_F(ConvolutionMatcherTest, GroupConvsSameKernelSize) { + const auto param = std::make_shared(Type_t::f32, Shape({1, 4, 10, 10})); + const auto weights = std::make_shared(Type_t::f32, Shape({2, 10, 2, 3, 3}), 1); + const auto op1 = std::make_shared(param, weights, Strides(0, 0), CoordinateDiff(0, 0), + CoordinateDiff(0, 0), Strides(0, 0)); + + const auto param2 = std::make_shared(Type_t::f32, Shape({1, 6, 20, 20})); + const auto weights2 = std::make_shared(Type_t::f32, Shape({2, 10, 3, 3, 3}), 1); + const auto op2 = std::make_shared(param2, weights2, Strides(0, 0), CoordinateDiff(0, 0), + CoordinateDiff(0, 0), Strides(0, 0)); + ASSERT_TRUE(matcher.match(op1, op2, op_info)); +} + +// Check that two group convolutions with different input shapes but same kernel size are match each other +TEST_F(ConvolutionMatcherTest, GroupConvsDifferentKernelSize) { + const auto param = std::make_shared(Type_t::f32, Shape({1, 4, 10, 10})); + const auto weights = std::make_shared(Type_t::f32, Shape({2, 10, 2, 3, 5}), 1); + const auto op1 = std::make_shared(param, weights, Strides(0, 0), CoordinateDiff(0, 0), + CoordinateDiff(0, 0), Strides(0, 0)); + + const auto param2 = std::make_shared(Type_t::f32, Shape({1, 6, 20, 20})); + const auto weights2 = std::make_shared(Type_t::f32, Shape({2, 10, 3, 3, 3}), 1); + const auto op2 = std::make_shared(param2, weights2, Strides(0, 0), CoordinateDiff(0, 0), + CoordinateDiff(0, 0), Strides(0, 0)); + ASSERT_FALSE(matcher.match(op1, op2, op_info)); +} \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/tests/matchers/generic_single_op.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/tests/matchers/generic_single_op.cpp index d2e7a701e63..00cff572a5d 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/tests/matchers/generic_single_op.cpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/tests/matchers/generic_single_op.cpp @@ -5,6 +5,7 @@ #include "gtest/gtest.h" #include "matchers/single_op.hpp" #include "ngraph/ops.hpp" +#include "functional_test_utils/include/functional_test_utils/layer_test_utils/op_info.hpp" using namespace ngraph::op; using namespace ngraph; @@ -14,9 +15,11 @@ class SingleOpMatcherTest : public ::testing::Test { protected: void SetUp() { matcher = SubgraphsDumper::SingleOpMatcher(); + op_info = LayerTestsUtils::OPInfo(); } SubgraphsDumper::SingleOpMatcher matcher; + LayerTestsUtils::OPInfo op_info; }; @@ -28,7 +31,7 @@ TEST_F(SingleOpMatcherTest, AllPortsAreConsts_IgnoreConstPortVals) { const auto const2 = std::make_shared(Type_t::f32, Shape({5, 5}), 2); const auto op2 = std::make_shared(const2, shape_pattern, false); - ASSERT_TRUE(matcher.match(op1, op2)); + ASSERT_TRUE(matcher.match(op1, op2, op_info)); } // Check match of equal nodes @@ -37,7 +40,7 @@ TEST_F(SingleOpMatcherTest, AllPortsAreParams_NodesEqual) { const auto param2 = std::make_shared(element::Type_t::f32, Shape({10, 20})); const auto op1 = std::make_shared<::Concat>(OutputVector({param1, param2}), 1); const auto op2 = std::make_shared<::Concat>(OutputVector({param1, param2}), 1); - ASSERT_TRUE(matcher.match(op1, op2)); + ASSERT_TRUE(matcher.match(op1, op2, op_info)); } // Check nodes doesn't match - different input ranks @@ -49,7 +52,7 @@ TEST_F(SingleOpMatcherTest, AllPortsAreParams_RanksNotEqual) { const auto param3 = std::make_shared(element::Type_t::f32, Shape({10, 40, 10})); const auto param4 = std::make_shared(element::Type_t::f32, Shape({10, 40, 10})); const auto op2 = std::make_shared<::Concat>(OutputVector({param3, param4}), 1); - ASSERT_FALSE(matcher.match(op1, op2)); + ASSERT_FALSE(matcher.match(op1, op2, op_info)); } // Check nodes doesn't match - different input element types @@ -61,7 +64,7 @@ TEST_F(SingleOpMatcherTest, AllPortsAreParams_TypesNotEqual) { const auto param3 = std::make_shared(element::Type_t::f16, Shape({10, 10})); const auto param4 = std::make_shared(element::Type_t::f16, Shape({10, 20})); const auto op2 = std::make_shared<::Concat>(OutputVector({param3, param4}), 1); - ASSERT_FALSE(matcher.match(op1, op2)); + ASSERT_FALSE(matcher.match(op1, op2, op_info)); } // Check nodes doesn't match - different input element types @@ -73,7 +76,7 @@ TEST_F(SingleOpMatcherTest, AllPortsAreParams_AttrsNotEqual) { const auto param3 = std::make_shared(element::Type_t::f32, Shape({10, 10, 10})); const auto param4 = std::make_shared(element::Type_t::f32, Shape({10, 10, 10})); const auto op2 = std::make_shared<::Concat>(OutputVector({param3, param4}), 2); - ASSERT_FALSE(matcher.match(op1, op2)); + ASSERT_FALSE(matcher.match(op1, op2, op_info)); } // Check nodes Add OPs match with different constants on ports @@ -85,5 +88,5 @@ TEST_F(SingleOpMatcherTest, ChecAddOpConfiguration) { const auto const3 = std::make_shared(Type_t::f32, Shape({5, 5}), 3); const auto const4 = std::make_shared(Type_t::f32, Shape({5, 5}), 4); const auto op2 = std::make_shared(const1, const2); - ASSERT_TRUE(matcher.match(op1, op2)); + ASSERT_TRUE(matcher.match(op1, op2, op_info)); } \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp index ef4cbf639bf..86158025ddf 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp @@ -53,6 +53,7 @@ std::vector disabledTestPatterns() { R"(.*BinaryConvolutionLayerTest.*)", R"(.*ClampLayerTest.*netPrc=(I64|I32).*)", R"(.*ClampLayerTest.*netPrc=U64.*)", + // TODO: 42538. Unexpected application crush R"(.*CoreThreadingTestsWithIterations\.smoke_LoadNetwork.t.*)", // incorrect reference implementation @@ -70,8 +71,19 @@ std::vector disabledTestPatterns() { R"(.*CoreThreading.*smoke_QueryNetwork.*targetDevice=AUTO_config.*)", // incorrect reference implementation. Issues: 55384, 54528, 54529 R"(.*DFTLayerTest.*)", + // TODO: 54718 Accuracy mismatch + R"(.*GroupDeconv_2D_DW_BF16.*K\(3\.3\)_S\(1\.1\).*primitive=jit_avx512_dw.*)", + R"(.*GroupDeconv_2D_DW_BF16.*K\(3\.3\)_S\(2\.2\).*primitive=jit_avx512_dw.*)", }; - + // TODO: 54718 Accuracy mismatch +#ifdef _WIN32 + retVector.insert(retVector.end(), { + R"(.*GroupDeconv_3D_Planar_BF16.*K\(3\.3\.3\)_S\(1\.1\.1\).*inFmts=ncdhw_outFmts=ncdhw_primitive=jit_gemm_PluginConf.*)", + R"(.*GroupDeconv_3D_Planar_BF16.*K\(3\.3\.3\)_S\(2\.2\.2\).*inFmts=ncdhw_outFmts=ncdhw_primitive=jit_gemm_PluginConf.*)", + R"(.*GroupDeconv_3D_Planar_BF16.*K\(1\.1\.1\)_S\(1\.1\.1\).*inFmts=ncdhw_outFmts=ncdhw_primitive=jit_gemm_PluginConf.*)", + R"(.*GroupDeconv_3D_Planar_BF16.*K\(1\.1\.1\)_S\(2\.2\.2\).*inFmts=ncdhw_outFmts=ncdhw_primitive=jit_gemm_PluginConf.*)", + }); +#endif if (!InferenceEngine::with_cpu_x86_avx512_core()) { // on platforms which do not support bfloat16, we are disabling bf16 tests since there are no bf16 primitives, // tests are useless on such platforms diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/skip_tests_config.cpp index 5252cddbd95..831c0fe7878 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/skip_tests_config.cpp @@ -39,5 +39,7 @@ std::vector disabledTestPatterns() { ".*PreprocessConversionTest.*oPRC=U8.*", // TODO: Issue 54163 R"(.*ActivationLayerTest.*SoftPlus.*)", + // TODO: Issue 54722 + R"(.*IS=\(16\.16\.96\)\(96\)_eltwiseOpType=FloorMod_secondaryInputType=PARAMETER_opType=VECTOR_netPRC=FP32.*)", }; } diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/read_ir/read_ir.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/read_ir/read_ir.hpp index f71ae7c0ab2..00638c5d468 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/read_ir/read_ir.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/read_ir/read_ir.hpp @@ -23,5 +23,7 @@ protected: private: std::string pathToModel; + std::string sourceModel; + std::vector> ocuranceInModels; }; } // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/read_ir/read_ir.cpp b/inference-engine/tests/functional/shared_test_classes/src/read_ir/read_ir.cpp index 3f966b858f1..6a2d812aa14 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/read_ir/read_ir.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/read_ir/read_ir.cpp @@ -4,13 +4,14 @@ #include "common_test_utils/file_utils.hpp" #include "functional_test_utils/core_config.hpp" +#include "functional_test_utils/layer_test_utils/op_info.hpp" #include "shared_test_classes/read_ir/read_ir.hpp" #include "shared_test_classes/read_ir/compare_results.hpp" #include "shared_test_classes/read_ir/generate_inputs.hpp" namespace LayerTestsDefinitions { -std::string ReadIRTest::getTestCaseName(const testing::TestParamInfo>& obj) { +std::string ReadIRTest::getTestCaseName(const testing::TestParamInfo> &obj) { std::string pathToModel, deviceName; std::tie(pathToModel, deviceName) = obj.param; @@ -26,20 +27,66 @@ std::string ReadIRTest::getTestCaseName(const testing::TestParamInfoGetParam(); - cnnNetwork = getCore()->ReadNetwork(pathToModel); - function = cnnNetwork.getFunction(); + auto net = getCore()->ReadNetwork(pathToModel); + function = net.getFunction(); + const auto metaFile = CommonTestUtils::replaceExt(pathToModel, "meta"); + if (CommonTestUtils::fileExists(metaFile)) { + pugi::xml_document doc; + doc.load_file(metaFile.c_str()); + auto models = doc.child("meta_info").child("models"); + sourceModel = models.child("initial_model").attribute("name").as_string(); + for (const auto &model : models.children("model")) { + ocuranceInModels.push_back({model.attribute("name").as_string(), model.attribute("count").as_uint()}); + } + auto portsInfo = doc.child("meta_info").child("ports_info"); + auto getPortInfo = [&](size_t id) { + LayerTestsUtils::PortInfo info; + for (const auto &p : portsInfo.children()) { + if (p.attribute("id").as_uint() == id) { + info.convert_to_const = p.attribute("convert_to_const").as_bool(); + if (std::strcmp(p.attribute("min").as_string(), "undefined") != 0) { + info.min = p.attribute("min").as_double(); + } else { + info.min = -10; + } + if (std::strcmp(p.attribute("max").as_string(), "undefined") != 0) { + info.max = p.attribute("max").as_double(); + } else { + info.max = 10; + } + break; + } + } + return info; + }; + for (const auto ¶m : function->get_parameters()) { + auto idx = function->get_parameter_index(param); + auto info = getPortInfo(idx); + if (info.convert_to_const) { + const auto constant = ngraph::builder::makeConstant(param->get_element_type(), + param->get_shape(), + std::vector{}, + true, + info.max, + info.min, + 1); + ngraph::replace_node(param, constant); + function->remove_parameter(param); + } + } + } } void ReadIRTest::GenerateInputs() { auto inputMap = getInputMap(); - const auto& inputsInfo = executableNetwork.GetInputsInfo(); - for (const auto& param : function->get_parameters()) { + const auto &inputsInfo = executableNetwork.GetInputsInfo(); + for (const auto ¶m : function->get_parameters()) { const auto infoIt = inputsInfo.find(param->get_friendly_name()); GTEST_ASSERT_NE(infoIt, inputsInfo.cend()); - const auto& info = infoIt->second; + const auto &info = infoIt->second; for (size_t i = 0; i < param->get_output_size(); i++) { - for (const auto& node : param->get_output_target_inputs(i)) { + for (const auto &node : param->get_output_target_inputs(i)) { const auto nodePtr = node.get_node()->shared_from_this(); auto it = inputMap.find(nodePtr->get_type_info()); for (size_t port = 0; port < nodePtr->get_input_size(); ++port) { @@ -55,7 +102,7 @@ void ReadIRTest::GenerateInputs() { void ReadIRTest::Compare(const std::vector> &expected, const std::vector &actual) { auto compareMap = getCompareMap(); - for (const auto& result : function->get_results()) { + for (const auto &result : function->get_results()) { for (size_t i = 0; i < result->get_input_size(); ++i) { const auto inputNode = result->get_input_node_shared_ptr(i); auto it = compareMap.find(inputNode->get_type_info()); @@ -66,19 +113,14 @@ void ReadIRTest::Compare(const std::vector> &expected, std::vector ReadIRTest::GetOutputs() { std::vector outputs; -// CNNNetworkNGraphImpl::getOVNameForTensor works incorrect: _tensorNames is empty -// for (const auto& result : function->get_results()) { -// outputs.push_back(inferRequest.GetBlob(cnnNetwork.getOVNameForTensor(result->get_friendly_name()))); -// } - - for (const auto& result : function->get_results()) { + for (const auto &result : function->get_results()) { for (size_t inPort = 0; inPort < result->get_input_size(); ++inPort) { - const auto& inputNode = result->get_input_node_shared_ptr(inPort); + const auto &inputNode = result->get_input_node_shared_ptr(inPort); for (size_t outPort = 0; outPort < inputNode->get_output_size(); ++outPort) { - for (const auto& out : inputNode->get_output_target_inputs(outPort)) { + for (const auto &out : inputNode->get_output_target_inputs(outPort)) { if (out.get_node()->shared_from_this() == result) { std::string name = inputNode->get_friendly_name(); - if (inputNode->get_output_size() > 1) { + if (inputNode->get_output_size() > 1) { name += "." + std::to_string(outPort); } outputs.push_back(inferRequest.GetBlob(name)); diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/layer_test_utils/op_info.hpp b/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/layer_test_utils/op_info.hpp new file mode 100644 index 00000000000..715eaec4990 --- /dev/null +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/layer_test_utils/op_info.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +namespace LayerTestsUtils { +struct PortInfo { + double min; + double max; + bool convert_to_const; + + PortInfo(double min, double max, bool convert_to_const) : min(min), max(max), + convert_to_const(convert_to_const) {} + PortInfo() { + min = std::numeric_limits::min(); + max = std::numeric_limits::max(); + convert_to_const = false; + } +}; + +struct OPInfo { + std::string source_model; + std::map found_in_models; + std::map ports_info; + + OPInfo(const std::string &source_model) : source_model(source_model) { + found_in_models = {{source_model, 1}}; + ports_info = {}; + } + + OPInfo() = default; +}; +} // namespace LayerTestsUtils \ No newline at end of file diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp index 475bbdd2ac6..802535430cd 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp @@ -28,7 +28,7 @@ makeParams(const element::Type &type, const std::vector std::shared_ptr makeConstant(const element::Type &type, const std::vector &shape, const std::vector &data, bool random = false, - uint32_t upTo = 10, uint32_t startFrom = 1, const int seed = 1) { + T upTo = 10, T startFrom = 1, const int seed = 1) { std::shared_ptr weightsNode; #define makeNode(TYPE) \ diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/data_utils.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/data_utils.hpp index 8c53df8c0c7..02f72e0555e 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/data_utils.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/data_utils.hpp @@ -17,42 +17,64 @@ namespace Utils { template std::vector::value_type> inline -generateVector(size_t vec_len, uint32_t upTo = 10, uint32_t startFrom = 1, int32_t seed = 1) { - std::vector::value_type> res; +generateVector(size_t vec_len, + typename ngraph::helpers::nGraphTypesTrait::value_type upTo = 10, + typename ngraph::helpers::nGraphTypesTrait::value_type startFrom = 1, + int32_t seed = 1) { + using dataType = typename ngraph::helpers::nGraphTypesTrait::value_type; + std::vector res(vec_len); std::mt19937 gen(seed); - // chose values between this range to avoid type overrun (e.g. in case of I8 precision) - std::uniform_int_distribution dist(startFrom, upTo); + if (std::is_floating_point()) { + // chose values between this range to avoid type overrun (e.g. in case of I8 precision) + std::uniform_real_distribution dist(startFrom, upTo); + // explicitly include data range borders to avoid missing the corner values while data generation + res[0] = startFrom; + res[vec_len - 1] = upTo; + for (size_t i = 1; i < vec_len - 1; i++) { + res[i] = static_cast(dist(gen)); + } + return res; + } else { + // chose values between this range to avoid type overrun (e.g. in case of I8 precision) + std::uniform_int_distribution dist(startFrom, upTo); + // explicitly include data range borders to avoid missing the corner values while data generation + res[0] = startFrom; + res[vec_len - 1] = upTo; + for (size_t i = 1; i < vec_len - 1; i++) { + res[i] = static_cast(dist(gen)); + } + return res; + } +} - for (size_t i = 0; i < vec_len; i++) { - res.push_back( - static_cast::value_type>(dist(gen))); +std::vector inline +generateF16Vector(size_t vec_len, ngraph::float16 upTo = 10, ngraph::float16 startFrom = 1, int32_t seed = 1) { + std::vector res(vec_len); + std::mt19937 gen(seed); + // chose values between this range to avoid type overrun (e.g. in case of I8 precision) + std::uniform_real_distribution dist(startFrom, upTo); + // explicitly include data range borders to avoid missing the corner values while data generation + res[0] = startFrom; + res[vec_len - 1] = upTo; + for (size_t i = 1; i < vec_len - 1; i++) { + res[i] = ngraph::float16(dist(gen)); } return res; } -std::vector inline generateF16Vector(size_t vec_len, uint32_t upTo = 10, uint32_t startFrom = 1, int32_t seed = 1) { - std::vector res; +std::vector inline +generateBF16Vector(size_t vec_len, ngraph::bfloat16 upTo = 10, ngraph::bfloat16 startFrom = 1, int32_t seed = 1) { + std::vector res(vec_len); std::mt19937 gen(seed); // chose values between this range to avoid type overrun (e.g. in case of I8 precision) - std::uniform_int_distribution dist(startFrom, upTo); - - for (size_t i = 0; i < vec_len; i++) { - res.emplace_back(ngraph::float16(static_cast(dist(gen)))); - } - return res; -} - -std::vector inline generateBF16Vector(size_t vec_len, uint32_t upTo = 10, uint32_t startFrom = 1, int32_t seed = 1) { - std::vector res; - - std::mt19937 gen(seed); - // chose values between this range to avoid type overrun (e.g. in case of I8 precision) - std::uniform_int_distribution dist(startFrom, upTo); - - for (size_t i = 0; i < vec_len; i++) { - res.emplace_back(ngraph::bfloat16(static_cast(dist(gen)))); + std::uniform_real_distribution dist(startFrom, upTo);; + // explicitly include data range borders to avoid missing the corner values while data generation + res[0] = startFrom; + res[vec_len - 1] = upTo; + for (size_t i = 1; i < vec_len - 1; i++) { + res[i] = ngraph::bfloat16(dist(gen)); } return res; } @@ -61,7 +83,7 @@ template std::vector castVector(const std::vector &vec) { std::vector resVec; resVec.reserve(vec.size()); - for (auto& el : vec) { + for (auto &el : vec) { resVec.push_back(static_cast(el)); } return resVec; diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/batch_norm.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/batch_norm.cpp index 01c01306cea..1963cf896f3 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/batch_norm.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/batch_norm.cpp @@ -15,9 +15,9 @@ std::shared_ptr makeBatchNormInference(const ngraph::Output& size_t C = data.get_shape().at(1); bool random = true; std::vector values(C); - auto gamma = ngraph::builder::makeConstant(ngPrc, ngraph::Shape{C}, values, random, 1, 0); - auto beta = ngraph::builder::makeConstant(ngPrc, ngraph::Shape{C}, values, random, 1, 0); - auto mean = ngraph::builder::makeConstant(ngPrc, ngraph::Shape{C}, values, random, 1, 0); + auto gamma = ngraph::builder::makeConstant(ngPrc, ngraph::Shape{C}, values, random, 1.f, 0.f); + auto beta = ngraph::builder::makeConstant(ngPrc, ngraph::Shape{C}, values, random, 1.f, 0.f); + auto mean = ngraph::builder::makeConstant(ngPrc, ngraph::Shape{C}, values, random, 1.f, 0.f); // Fill the vector for variance with positive values std::default_random_engine gen; diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/fake_quantize.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/fake_quantize.cpp index d8351a4bd56..63deb052292 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/fake_quantize.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/fake_quantize.cpp @@ -69,10 +69,10 @@ std::shared_ptr makeFakeQuantize(const ngraph::Output(in, inputLowNode, inputHighNode, outputLowNode, outputHighNode, levels); diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp index 6c36cbfe453..5f2484b73a5 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp @@ -43,7 +43,7 @@ std::shared_ptr makeGRU(const OutputVector& in, for (size_t i = 0; i <= in[0].get_shape().at(0); ++i) { std::vector lengths; seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true, - in[0].get_shape()[1], 0); + static_cast(in[0].get_shape()[1]), 0.f); } break; } diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp index 4c136086b68..8a8865643c3 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp @@ -41,7 +41,7 @@ std::shared_ptr makeLSTM(const std::vector>& for (size_t i = 0; i <= in[0].get_shape().at(0); ++i) { std::vector lengths; seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true, - in[0].get_shape()[1], 0); + static_cast(in[0].get_shape()[1]), 0.f); } break; } diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp index 95103b12cbc..55b1b661c2b 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp @@ -41,7 +41,7 @@ std::shared_ptr makeRNN(const OutputVector& in, for (size_t i = 0; i <= in[0].get_shape().at(0); ++i) { std::vector lengths; seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true, - in[0].get_shape()[1], 0); + static_cast(in[0].get_shape()[1]), 0.f); } break; } diff --git a/ngraph/core/src/op/interpolate.cpp b/ngraph/core/src/op/interpolate.cpp index 43a966bbca5..c5d77d33922 100644 --- a/ngraph/core/src/op/interpolate.cpp +++ b/ngraph/core/src/op/interpolate.cpp @@ -268,7 +268,7 @@ void op::v4::Interpolate::validate_and_infer_types() // If the input 'axes' is given and this input is not Constant, we cannot infer any elements // of the output shape. Hence, all components of the output shape should be dynamic. - if (input_values().size() == 4 && !is_type(input_value(3).get_node())) + if (input_values().size() == 4 && !has_and_set_equal_bounds(input_value(3))) { PartialShape output_shape = std::vector(input_rank, Dimension::dynamic()); set_output_type(0, get_input_element_type(0), output_shape); diff --git a/ngraph/core/src/op/topk.cpp b/ngraph/core/src/op/topk.cpp index 9cd2fa3ae0a..8d924e2d12b 100644 --- a/ngraph/core/src/op/topk.cpp +++ b/ngraph/core/src/op/topk.cpp @@ -306,7 +306,8 @@ void op::v1::TopK::validate_and_infer_types() } else { - output_shape[m_normalized_axis] = -1; + output_shape[m_normalized_axis] = + Dimension(0, input_partial_shape[m_normalized_axis].get_max_length()); } } diff --git a/ngraph/test/type_prop/interpolate.cpp b/ngraph/test/type_prop/interpolate.cpp index 504b8f8accc..e68a3d02855 100644 --- a/ngraph/test/type_prop/interpolate.cpp +++ b/ngraph/test/type_prop/interpolate.cpp @@ -42,10 +42,7 @@ TEST(type_prop, interpolate_v4_non_constant_axes_scales) auto target_shape = std::make_shared(element::i64, Shape{15, 30}); auto scales = op::Constant::create(element::f32, Shape{2}, {0.5f, 0.5f}); - auto start = std::make_shared(element::i32, Shape{}, std::vector{2}); - auto stop = std::make_shared(element::i32, Shape{}, std::vector{4}); - auto step = std::make_shared(element::i32, Shape{}, std::vector{1}); - auto axes = std::make_shared(start, stop, step, element::i32); + auto axes = std::make_shared(element::i32, PartialShape{2}); InterpolateAttrs attrs; attrs.mode = InterpolateMode::nearest; @@ -70,10 +67,7 @@ TEST(type_prop, interpolate_v4_non_constant_axes_sizes) auto target_shape = std::make_shared(element::i64, Shape{15, 30}); auto scales = op::Constant::create(element::f32, Shape{2}, {0.5f, 0.5f}); - auto start = std::make_shared(element::i32, Shape{}, std::vector{2}); - auto stop = std::make_shared(element::i32, Shape{}, std::vector{4}); - auto step = std::make_shared(element::i32, Shape{}, std::vector{1}); - auto axes = std::make_shared(start, stop, step, element::i32); + auto axes = std::make_shared(element::i32, PartialShape{2}); InterpolateAttrs attrs; attrs.mode = InterpolateMode::nearest; diff --git a/ngraph/test/type_prop/top_k.cpp b/ngraph/test/type_prop/top_k.cpp index 4733b3e911a..768f533cc0c 100644 --- a/ngraph/test/type_prop/top_k.cpp +++ b/ngraph/test/type_prop/top_k.cpp @@ -71,7 +71,7 @@ TYPED_TEST_P(topk_type_prop, topk_v1_partial_ouptut) { auto k = make_shared(element::i32, PartialShape({})); auto topk = make_shared(data, k, 1, "max", "value"); - EXPECT_EQ(topk->get_output_partial_shape(0), PartialShape({2, -1})); + EXPECT_EQ(topk->get_output_partial_shape(0), PartialShape({2, Dimension(0, 10)})); } { auto k = make_shared(element::i32, Shape{}, 3); @@ -91,7 +91,7 @@ TYPED_TEST_P(topk_type_prop, topk_rank_static_k_unknown) const auto k = make_shared(element::i32, PartialShape({})); const auto topk = make_shared(data, k, axis, "max", "value"); - const PartialShape fully_dynamic_axis_shape{1, Dimension::dynamic(), 100}; + const PartialShape fully_dynamic_axis_shape{1, Dimension(0, 10), 100}; EXPECT_EQ(topk->get_output_partial_shape(0), fully_dynamic_axis_shape); } { From 647acffd1d94d56f05736ebf96e1c9ed62fb28b7 Mon Sep 17 00:00:00 2001 From: Vladimir Paramuzov Date: Mon, 17 May 2021 13:21:24 +0300 Subject: [PATCH 89/99] [IE CLDNN] Fixed eltwise shrink when node has fused ops (#5570) --- .../thirdparty/clDNN/src/graph_optimizer/eltwise_shrinking.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/eltwise_shrinking.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/eltwise_shrinking.cpp index d4ace81e171..9b52e8740ea 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/eltwise_shrinking.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/eltwise_shrinking.cpp @@ -84,7 +84,7 @@ void eltwise_shrinking::run(program_impl& p) { if (can_shrink) { // add stride for every eltwise's inputs to have shrinked output auto e = const_cast(&(*eltw)); - for (size_t dep = 0; dep < node->get_dependencies().size(); dep++) { + for (size_t dep = 0; dep < e->input_size(); dep++) { auto dep_stride_x = stride_x; auto dep_stride_y = stride_y; // don't shrink if input is broadcasted From d20900e235189ba53c38c8ace4a3389a69c84ce2 Mon Sep 17 00:00:00 2001 From: Mikhail Nosov Date: Mon, 17 May 2021 13:41:15 +0300 Subject: [PATCH 90/99] [Caching] Add caching options to benchmark app (#4909) * Python API for LoadNetwork by model file name * BenchmarkApp: Add caching and LoadNetworkFromFile support 2 new options are introduced - cache_dir - enables models caching - load_from_file - use new perform "LoadNetwork" by model file name Using both parameters will achieve maximum performance of read/load network on startup Tests: 1) Run "benchmark_app -h". Help will display 2 new options. After available devices there will be list of devices with cache support 2) ./benchmark_app -d CPU -i -load_from_file Verify that some test steps are skipped (related to ReadNetwork, re-shaping etc) 3) Pre-requisite: support of caching shall be enabled for Template plugin ./benchmark_app -d TEMPLATE -i -load_from_file -cache_dir someDir Verify that "someDir" is created and generated blob is available Run again, verify that loading works as well (should be faster as it will not load onnx model) 4) Run same test as (3), but without -load_from_file option. Verify that cache is properly created For some devices loadNetwork time shall be improved when cache is available * Removed additional timing prints * Correction from old code * Revert "Removed additional timing prints" Additional change - when .blob is chosen instead of .xml, it takes priority over caching flags * Removed new time printings As discussed, these time measurements like 'total first inference time' will be available in 'timeTests' scripts * Fix clang-format issues --- .../samples/benchmark_app/README.md | 2 ++ .../samples/benchmark_app/benchmark_app.hpp | 16 +++++++++ .../samples/benchmark_app/main.cpp | 26 ++++++++++++-- tools/benchmark/README.md | 5 +++ tools/benchmark/benchmark.py | 13 +++++++ tools/benchmark/main.py | 35 +++++++++++++++++-- tools/benchmark/parameters.py | 4 +++ 7 files changed, 96 insertions(+), 5 deletions(-) diff --git a/inference-engine/samples/benchmark_app/README.md b/inference-engine/samples/benchmark_app/README.md index 432e8b28ec0..7c61bc570d5 100644 --- a/inference-engine/samples/benchmark_app/README.md +++ b/inference-engine/samples/benchmark_app/README.md @@ -93,6 +93,8 @@ Options: -progress Optional. Show progress bar (can affect performance measurement). Default values is "false". -shape Optional. Set shape for input. For example, "input1[1,3,224,224],input2[1,4]" or "[1,3,224,224]" in case of one input size. -layout Optional. Prompts how network layouts should be treated by application. For example, "input1[NCHW],input2[NC]" or "[NCHW]" in case of one input size. + -cache_dir "" Optional. Enables caching of loaded models to specified directory. + -load_from_file Optional. Loads model from file directly without ReadNetwork. CPU-specific performance options: -nstreams "" Optional. Number of streams to use for inference on the CPU, GPU or MYRIAD devices diff --git a/inference-engine/samples/benchmark_app/benchmark_app.hpp b/inference-engine/samples/benchmark_app/benchmark_app.hpp index 8cc5d19c781..af18c908e31 100644 --- a/inference-engine/samples/benchmark_app/benchmark_app.hpp +++ b/inference-engine/samples/benchmark_app/benchmark_app.hpp @@ -122,6 +122,14 @@ static const char shape_message[] = "Optional. Set shape for input. For example, static const char layout_message[] = "Optional. Prompts how network layouts should be treated by application. " "For example, \"input1[NCHW],input2[NC]\" or \"[NCHW]\" in case of one input size."; +// @brief message for enabling caching +static const char cache_dir_message[] = "Optional. Enables caching of loaded models to specified directory. " + "List of devices which support caching is shown at the end of this message."; + +// @brief message for single load network +static const char load_from_file_message[] = "Optional. Loads model from file directly without ReadNetwork." + "All CNNNetwork options (like re-shape) will be ignored"; + // @brief message for quantization bits static const char gna_qb_message[] = "Optional. Weight bits for quantization: 8 or 16 (default)"; @@ -238,6 +246,12 @@ DEFINE_string(op, "", outputs_precision_message); /// Overwrites layout from ip and op options for specified layers."; DEFINE_string(iop, "", iop_message); +/// @brief Define parameter for cache model dir
+DEFINE_string(cache_dir, "", cache_dir_message); + +/// @brief Define flag for load network from model file by name without ReadNetwork
+DEFINE_bool(load_from_file, false, load_from_file_message); + /** * @brief This function show a help message */ @@ -262,6 +276,8 @@ static void showUsage() { std::cout << " -progress " << progress_message << std::endl; std::cout << " -shape " << shape_message << std::endl; std::cout << " -layout " << layout_message << std::endl; + std::cout << " -cache_dir \"\" " << cache_dir_message << std::endl; + std::cout << " -load_from_file " << load_from_file_message << std::endl; std::cout << std::endl << " device-specific performance options:" << std::endl; std::cout << " -nstreams \"\" " << infer_num_streams_message << std::endl; std::cout << " -nthreads \"\" " << infer_num_threads_message << std::endl; diff --git a/inference-engine/samples/benchmark_app/main.cpp b/inference-engine/samples/benchmark_app/main.cpp index 5a34e558cd3..849dc05ad33 100644 --- a/inference-engine/samples/benchmark_app/main.cpp +++ b/inference-engine/samples/benchmark_app/main.cpp @@ -330,7 +330,29 @@ int main(int argc, char* argv[]) { std::string topology_name = ""; benchmark_app::InputsInfo app_inputs_info; std::string output_name; - if (!isNetworkCompiled) { + + // Takes priority over config from file + if (!FLAGS_cache_dir.empty()) { + ie.SetConfig({{CONFIG_KEY(CACHE_DIR), FLAGS_cache_dir}}); + } + + if (FLAGS_load_from_file && !isNetworkCompiled) { + next_step(); + slog::info << "Skipping the step for loading network from file" << slog::endl; + next_step(); + slog::info << "Skipping the step for loading network from file" << slog::endl; + next_step(); + slog::info << "Skipping the step for loading network from file" << slog::endl; + auto startTime = Time::now(); + exeNetwork = ie.LoadNetwork(FLAGS_m, device_name); + auto duration_ms = double_to_string(get_total_ms_time(startTime)); + slog::info << "Load network took " << duration_ms << " ms" << slog::endl; + if (statistics) + statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS, {{"load network time (ms)", duration_ms}}); + if (batchSize == 0) { + batchSize = 1; + } + } else if (!isNetworkCompiled) { // ----------------- 4. Reading the Intermediate Representation network // ---------------------------------------- next_step(); @@ -363,7 +385,7 @@ int main(int argc, char* argv[]) { slog::info << "Reshaping network: " << getShapesString(shapes) << slog::endl; startTime = Time::now(); cnnNetwork.reshape(shapes); - auto duration_ms = double_to_string(get_total_ms_time(startTime)); + duration_ms = double_to_string(get_total_ms_time(startTime)); slog::info << "Reshape network took " << duration_ms << " ms" << slog::endl; if (statistics) statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS, {{"reshape network time (ms)", duration_ms}}); diff --git a/tools/benchmark/README.md b/tools/benchmark/README.md index 280b7a0ef53..50caa430fd4 100644 --- a/tools/benchmark/README.md +++ b/tools/benchmark/README.md @@ -142,6 +142,11 @@ Options: parameters. Please note, command line parameters have higher priority then parameters from configuration file. + -cdir CACHE_DIR, --cache_dir CACHE_DIR + Optional. Enable model caching to specified directory + -lfile [LOAD_FROM_FILE], --load_from_file [LOAD_FROM_FILE] + Optional. Loads model from file directly without + read_network. ``` Running the application with the empty list of options yields the usage message given above and an error message. diff --git a/tools/benchmark/benchmark.py b/tools/benchmark/benchmark.py index 754bdd194e7..c73477acfc2 100644 --- a/tools/benchmark/benchmark.py +++ b/tools/benchmark/benchmark.py @@ -46,6 +46,9 @@ class Benchmark: for device in config.keys(): self.ie.set_config(config[device], device) + def set_cache_dir(self, cache_dir: str): + self.ie.set_config({'CACHE_DIR': cache_dir}, '') + def read_network(self, path_to_model: str): model_filename = os.path.abspath(path_to_model) head, ext = os.path.splitext(model_filename) @@ -63,6 +66,16 @@ class Benchmark: return exe_network + def load_network_from_file(self, path_to_model: str, config = {}): + exe_network = self.ie.load_network(path_to_model, + self.device, + config=config, + num_requests=1 if self.api_type == 'sync' else self.nireq or 0) + # Number of requests + self.nireq = len(exe_network.requests) + + return exe_network + def import_network(self, path_to_file : str, config = {}): exe_network = self.ie.import_network(model_file=path_to_file, device_name=self.device, diff --git a/tools/benchmark/main.py b/tools/benchmark/main.py index 998e95638fb..29aff45742e 100644 --- a/tools/benchmark/main.py +++ b/tools/benchmark/main.py @@ -176,12 +176,41 @@ def run(args): benchmark.set_config(config) batch_size = args.batch_size - if not is_network_compiled: + if args.cache_dir: + benchmark.set_cache_dir(args.cache_dir) + + topology_name = "" + load_from_file_enabled = is_flag_set_in_command_line('load_from_file') or is_flag_set_in_command_line('lfile') + if load_from_file_enabled and not is_network_compiled: + next_step() + print("Skipping the step for loading network from file") + next_step() + print("Skipping the step for loading network from file") + next_step() + print("Skipping the step for loading network from file") + + # --------------------- 7. Loading the model to the device ------------------------------------------------- + next_step() + + start_time = datetime.utcnow() + exe_network = benchmark.load_network(args.path_to_model) + duration_ms = f"{(datetime.utcnow() - start_time).total_seconds() * 1000:.2f}" + logger.info(f"Load network took {duration_ms} ms") + if statistics: + statistics.add_parameters(StatisticsReport.Category.EXECUTION_RESULTS, + [ + ('load network time (ms)', duration_ms) + ]) + app_inputs_info, _ = get_inputs_info(args.shape, args.layout, args.batch_size, exe_network.input_info) + if batch_size == 0: + batch_size = 1 + elif not is_network_compiled: # --------------------- 4. Read the Intermediate Representation of the network ----------------------------- next_step() start_time = datetime.utcnow() ie_network = benchmark.read_network(args.path_to_model) + topology_name = ie_network.name duration_ms = f"{(datetime.utcnow() - start_time).total_seconds() * 1000:.2f}" logger.info(f"Read network took {duration_ms} ms") if statistics: @@ -281,7 +310,7 @@ def run(args): if statistics: statistics.add_parameters(StatisticsReport.Category.RUNTIME_CONFIG, [ - ('topology', ie_network.name), + ('topology', topology_name), ('target device', device_name), ('API', args.api_type), ('precision', "UNSPECIFIED"), @@ -308,7 +337,7 @@ def run(args): progress_bar = ProgressBar(progress_bar_total_count, args.stream_output, args.progress) if args.progress else None - duration_ms = f"{benchmark.first_infer(exe_network):.2f}" + duration_ms = f"{benchmark.first_infer(exe_network):.2f}" logger.info(f"First inference took {duration_ms} ms") if statistics: statistics.add_parameters(StatisticsReport.Category.EXECUTION_RESULTS, diff --git a/tools/benchmark/parameters.py b/tools/benchmark/parameters.py index ca29fb5158c..73e1a931928 100644 --- a/tools/benchmark/parameters.py +++ b/tools/benchmark/parameters.py @@ -124,6 +124,10 @@ def parse_args(): help='Optional. Specifies precision for all output layers of the network.') args.add_argument('-iop', '--input_output_precision', type=str, required=False, help='Optional. Specifies precision for input and output layers by name. Example: -iop "input:FP16, output:FP16". Notice that quotes are required. Overwrites precision from ip and op options for specified layers.') + args.add_argument('-cdir', '--cache_dir', type=str, required=False, default='', + help="Optional. Enable model caching to specified directory") + args.add_argument('-lfile', '--load_from_file', required=False, nargs='?', default=argparse.SUPPRESS, + help="Optional. Loads model from file directly without read_network.") parsed_args = parser.parse_args() return parsed_args From 8300e9d5a1f8c45afa850b13e0ea6467864d21e7 Mon Sep 17 00:00:00 2001 From: Patryk Elszkowski Date: Mon, 17 May 2021 12:44:31 +0200 Subject: [PATCH 91/99] update reshape spec (#5575) * update reshape spec * fix input description * use T_SHAPE instead T_INT Co-authored-by: Patryk Elszkowski --- docs/ops/shape/Reshape_1.md | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/docs/ops/shape/Reshape_1.md b/docs/ops/shape/Reshape_1.md index 23226edb3cb..10145480ccb 100644 --- a/docs/ops/shape/Reshape_1.md +++ b/docs/ops/shape/Reshape_1.md @@ -8,40 +8,41 @@ **Detailed description**: -*Reshape* layer takes two input tensors: the tensor to be resized and the output tensor shape. The values in the second tensor could be -1, 0 and any positive integer number. The two special values -1 and 0: +*Reshape* takes two input tensors: `data` to be resized and `shape` of the new output. The values in the `shape` could be `-1`, `0` and any positive integer number. The two special values `-1` and `0`: * `0` means "copy the respective dimension *(left aligned)* of the input tensor" if `special_zero` is set to `true`; otherwise it is a normal dimension and is applicable to empty tensors. - * `-1` means that this dimension is calculated to keep the overall elements count the same as in the input tensor. Not more than one `-1` can be used in a reshape operation. + * `-1` means that this dimension is calculated to keep the overall elements count the same as in the input tensor. Not more than one `-1` can be used in a reshape operation. -If `special_zero` is set to `true` index of `0` cannot be larger than the rank of the input tensor. +If `special_zero` is set to `true` index of `0` cannot be larger than the rank of the input tensor. **Attributes**: * *special_zero* - * **Description**: *special_zero* controls how zero values in `shape` are interpreted. If *special_zero* is `false`, then 0 is interpreted as-is which means that output shape will contain a zero dimension at the specified location. Input and output tensors are empty in this case. If *special_zero* is `true`, then all zeros in `shape` implies the copying of corresponding dimensions from `data.shape` into the output shape *(left aligned)*. + * **Description**: *special_zero* controls how zero values in `shape` are interpreted. If *special_zero* is `false`, then `0` is interpreted as-is which means that output shape will contain a zero dimension at the specified location. Input and output tensors are empty in this case. If *special_zero* is `true`, then all zeros in `shape` implies the copying of corresponding dimensions from `data.shape` into the output shape *(left aligned)*. * **Range of values**: `false` or `true` - * **Type**: boolean + * **Type**: `boolean` * **Default value**: None * **Required**: *yes* **Inputs**: -* **1**: `data` -- multidimensional input tensor of type *T*. *Required*. +* **1**: `data` a tensor of type T and arbitrary shape. **Required**. -* **2**: `shape` -- 1D tensor of type *T_SHAPE* describing output shape. *Required*. +* **2**: `shape` 1D tensor of type *T_SHAPE* describing output shape. **Required**. **Outputs**: -* **1**: Output tensor with the same content as a tensor at input `data` but with shape defined by input `shape`. +* **1**: Output tensor of type *T* with the same content as `data` input tensor but with shape defined by `shape` input tensor. **Types** -* *T*: supported type. +* *T*: any numeric type. -* *T_SHAPE*: supported integer type. +* *T_SHAPE*: any supported integer type. **Examples** +*Example 1: reshape empty tensor* ```xml @@ -65,6 +66,7 @@ If `special_zero` is set to `true` index of `0` cannot be larger than the rank o ``` +*Example 2: reshape tensor - preserve first dim, calculate second and fix value for third dim* ```xml @@ -89,6 +91,7 @@ If `special_zero` is set to `true` index of `0` cannot be larger than the rank o ``` +*Example 3: reshape tensor - preserve first two dims, fix value for third dim and calculate fourth* ```xml @@ -113,6 +116,7 @@ If `special_zero` is set to `true` index of `0` cannot be larger than the rank o ``` +*Example 4: reshape tensor - calculate first dim and preserve second dim* ```xml @@ -135,6 +139,7 @@ If `special_zero` is set to `true` index of `0` cannot be larger than the rank o ``` +*Example 5: reshape tensor - preserve first dim and calculate second dim* ```xml @@ -155,4 +160,4 @@ If `special_zero` is set to `true` index of `0` cannot be larger than the rank o -``` \ No newline at end of file +``` From c029b07d3486f1bb759a1e508387c7995902984d Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Mon, 17 May 2021 14:16:44 +0300 Subject: [PATCH 92/99] Deprecate unused Tensor methods (#5630) --- ngraph/core/include/ngraph/runtime/tensor.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ngraph/core/include/ngraph/runtime/tensor.hpp b/ngraph/core/include/ngraph/runtime/tensor.hpp index c886108fe72..c0891fb8a17 100644 --- a/ngraph/core/include/ngraph/runtime/tensor.hpp +++ b/ngraph/core/include/ngraph/runtime/tensor.hpp @@ -57,10 +57,12 @@ namespace ngraph /// \brief Get the stale value of the tensor. A tensor is stale if its data is /// changed. /// \return true if there is new data in this tensor + NGRAPH_DEPRECATED("This method is deprecated and will be removed in 2022.1 release") bool get_stale() const; /// \brief Set the stale value of the tensor. A tensor is stale if its data is /// changed. + NGRAPH_DEPRECATED("This method is deprecated and will be removed in 2022.1 release") void set_stale(bool val); /// \brief Write bytes directly into the tensor @@ -75,9 +77,11 @@ namespace ngraph /// \brief check tensor for new data, call may block. /// backends may use this to ensure tensor is updated (eg: lazy eval). + NGRAPH_DEPRECATED("This method is deprecated and will be removed in 2022.1 release") virtual void wait_for_read_ready() {} /// \brief notify tensor of new data, call may block. /// backends may use this as indication of new data in tensor. + NGRAPH_DEPRECATED("This method is deprecated and will be removed in 2022.1 release") virtual void wait_for_write_ready() {} protected: From 642a62d0e2d802f78e322bf69666dcc437d7c97b Mon Sep 17 00:00:00 2001 From: iliya mironov Date: Mon, 17 May 2021 15:03:22 +0300 Subject: [PATCH 93/99] Add axis support (#5242) * Add axis support * Update dequant extractor * Update qdeq ops * Refactoring quantize * Update dequantize resolver * Update dequantize op * Refactoring dequantize * Some fixes for quantize and dequantize * Update unit tests * Reafctoring quantize/dequantize axis support * Move quantize/dequantize resolvers to middle * hot fix * Fix unit tests * Fix unit tests * Update quintize resolver comment * Refactoring code according to code review * Fix according to review * Change order for transforms quantize pipline --- model-optimizer/automation/package_BOM.txt | 4 +- .../front/onnx/dequantize_linear_ext.py | 7 +- .../front/onnx/dequantize_linear_resolver.py | 40 -- .../front/onnx/quantize_linear_ext.py | 2 +- .../front/onnx/quantize_linear_resolver.py | 69 ---- .../middle/dequantize_linear_resolver.py | 66 ++++ .../extensions/middle/quantize_fuses.py | 3 +- .../middle/quantize_linear_resolver.py | 101 +++++ .../extensions/ops/dequantize_linear.py | 4 +- .../extensions/ops/quantize_linear.py | 4 +- model-optimizer/mo/ops/broadcast.py | 4 +- .../onnx/dequantize_linear_resolver_test.py | 84 ---- .../onnx/quantize_linear_resolver_test.py | 144 ------- .../middle/dequantize_linear_resolver_test.py | 237 +++++++++++ .../middle/quantize_linear_resolver_test.py | 369 ++++++++++++++++++ 15 files changed, 790 insertions(+), 348 deletions(-) delete mode 100644 model-optimizer/extensions/front/onnx/dequantize_linear_resolver.py delete mode 100644 model-optimizer/extensions/front/onnx/quantize_linear_resolver.py create mode 100644 model-optimizer/extensions/middle/dequantize_linear_resolver.py create mode 100644 model-optimizer/extensions/middle/quantize_linear_resolver.py delete mode 100644 model-optimizer/unit_tests/extensions/front/onnx/dequantize_linear_resolver_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/onnx/quantize_linear_resolver_test.py create mode 100644 model-optimizer/unit_tests/extensions/middle/dequantize_linear_resolver_test.py create mode 100644 model-optimizer/unit_tests/extensions/middle/quantize_linear_resolver_test.py diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index c18d0f8dd93..9b5a25d9543 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -276,7 +276,6 @@ extensions/front/onnx/cumsum_ext.py extensions/front/onnx/deformable_conv_ext.py extensions/front/onnx/depth_to_space_ext.py extensions/front/onnx/dequantize_linear_ext.py -extensions/front/onnx/dequantize_linear_resolver.py extensions/front/onnx/detection_output.py extensions/front/onnx/detectionoutput_ext.py extensions/front/onnx/dropout_ext.py @@ -328,7 +327,6 @@ extensions/front/onnx/proposal_ext.py extensions/front/onnx/quantize_dequantize_linear.py extensions/front/onnx/quantize_ext.py extensions/front/onnx/quantize_linear_ext.py -extensions/front/onnx/quantize_linear_resolver.py extensions/front/onnx/range_ext.py extensions/front/onnx/reduce_ext.py extensions/front/onnx/remove_filtering_boxes_by_size.py @@ -580,6 +578,7 @@ extensions/middle/DecomposeBidirectionalRNNSequence.py extensions/middle/Deconvolution3rdInputNormalization.py extensions/middle/DeleteControlFlowEdges.py extensions/middle/DeleteNotExecutable.py +extensions/middle/dequantize_linear_resolver.py extensions/middle/DilatedConvolution.py extensions/middle/EltwiseChecker.py extensions/middle/EltwiseInputReshape.py @@ -614,6 +613,7 @@ extensions/middle/permute_tensor_iterator.py extensions/middle/PoolV2ToAttributedPool.py extensions/middle/preprocessing.py extensions/middle/quantize_fuses.py +extensions/middle/quantize_linear_resolver.py extensions/middle/ReluQuantizeFuse.py extensions/middle/RemoveDuplicationMemory.py extensions/middle/RemoveIdentity.py diff --git a/model-optimizer/extensions/front/onnx/dequantize_linear_ext.py b/model-optimizer/extensions/front/onnx/dequantize_linear_ext.py index 73ebaf958d8..83e1628c644 100644 --- a/model-optimizer/extensions/front/onnx/dequantize_linear_ext.py +++ b/model-optimizer/extensions/front/onnx/dequantize_linear_ext.py @@ -14,8 +14,9 @@ class DequantizeLinearFrontExtractor(FrontExtractorOp): @classmethod def extract(cls, node): + attrs = {} if get_onnx_opset_version(node) >= 13: - log.warning('Ignoring "axis" attribute for DequantizeLinear-{} node, inference might be incorrect.'.format( - get_onnx_opset_version(node))) - DequantizeLinear.update_node_stat(node) + axis = onnx_attr(node, 'axis', 'i', default=None) + attrs.update(axis=axis) + DequantizeLinear.update_node_stat(node, attrs) return cls.enabled diff --git a/model-optimizer/extensions/front/onnx/dequantize_linear_resolver.py b/model-optimizer/extensions/front/onnx/dequantize_linear_resolver.py deleted file mode 100644 index 1c2ab410c1b..00000000000 --- a/model-optimizer/extensions/front/onnx/dequantize_linear_resolver.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from extensions.front.onnx.quantize_dequantize_linear import QuantizeDequantizeLinear -from extensions.ops.Cast import Cast -from extensions.ops.elementwise import Mul, Sub -from mo.front.common.replacement import FrontReplacementOp -from mo.graph.graph import Graph, Node, rename_nodes -from mo.middle.passes.convert_data_type import data_type_str_to_np - - -class DequantizeLinearResolver(FrontReplacementOp): - """ - DequantizeLinear can be replace with the following formula: y = (x - x_zero_point) * x_scale - """ - op = "DequantizeLinear" - enabled = True - - def run_after(self): - return [QuantizeDequantizeLinear] - - def replace_op(self, graph: Graph, node: Node): - node_name = node.soft_get('name', node.id) - model_data_type = data_type_str_to_np(graph.graph['cmd_params'].data_type) - cast = Cast(graph, {'dst_type': model_data_type, 'name': node_name + '/Cast'}).create_node() - node.in_port(0).get_connection().set_destination(cast.in_port(0)) - mul = Mul(graph, {}).create_node() - - if node.is_in_port_connected(2): - sub = Sub(graph, {'name': node_name + '/Sub'}).create_node() - cast.out_port(0).connect(sub.in_port(0)) - node.in_port(2).get_connection().set_destination(sub.in_port(1)) - sub.out_port(0).connect(mul.in_port(0)) - else: - cast.out_port(0).connect(mul.in_port(0)) - - node.in_port(1).get_connection().set_destination(mul.in_port(1)) - rename_nodes([(node, node_name + '/TBD'), (mul, node_name)]) - - return [mul.id] diff --git a/model-optimizer/extensions/front/onnx/quantize_linear_ext.py b/model-optimizer/extensions/front/onnx/quantize_linear_ext.py index 8d329d0cbff..e399138a694 100644 --- a/model-optimizer/extensions/front/onnx/quantize_linear_ext.py +++ b/model-optimizer/extensions/front/onnx/quantize_linear_ext.py @@ -14,7 +14,7 @@ class QuantizeLinearFrontExtractor(FrontExtractorOp): def extract(cls, node): attrs = {} if get_onnx_opset_version(node) >= 13: - axis = onnx_attr(node, 'axis', 'i', default=1) + axis = onnx_attr(node, 'axis', 'i', default=None) attrs.update(axis=axis) QuantizeLinear.update_node_stat(node, attrs) return cls.enabled diff --git a/model-optimizer/extensions/front/onnx/quantize_linear_resolver.py b/model-optimizer/extensions/front/onnx/quantize_linear_resolver.py deleted file mode 100644 index 1b9df08c99c..00000000000 --- a/model-optimizer/extensions/front/onnx/quantize_linear_resolver.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np - -from extensions.front.onnx.quantize_dequantize_linear import QuantizeDequantizeLinear -from extensions.ops.Cast import Cast -from extensions.ops.elementwise import Mul -from extensions.ops.fakequantize import FakeQuantize -from mo.front.common.partial_infer.utils import float_array -from mo.front.common.replacement import FrontReplacementOp -from mo.front.tf.graph_utils import create_op_with_const_inputs -from mo.graph.graph import Graph, Node, rename_nodes -from mo.ops.const import Const -from mo.utils.error import Error - - -class QuantizeLinearResolver(FrontReplacementOp): - """ - Replaces QuantizeLinear with FakeQuantize - """ - op = "QuantizeLinear" - enabled = True - - def run_after(self): - return [QuantizeDequantizeLinear] - - def replace_op(self, graph: Graph, node: Node): - node_name = node.soft_get('name', node.id) - - if node.is_in_port_connected(2): - zerop = node.in_port(2).get_source().node - else: - zerop = Const(graph, {'value': np.array(0, dtype=np.uint8), 'name': node_name + '/ZeroPoint'}).create_node() - - assert zerop.soft_get('type') == 'Const', 'only constant for zero_point is supported for QuantizeLinear' - zero_point_type = zerop.value.dtype - # data type affects range of output values: [-128..127] or [0..255] - if zero_point_type == np.int8: - output_low_value = -128.0 - output_high_value = 127.0 - elif zero_point_type == np.uint8: - output_low_value = 0.0 - output_high_value = 255.0 - else: - raise Error('Not expected type {} for zero point value in node {}'.format( - zero_point_type, zerop.soft_get('name'))) - fake_quantize = create_op_with_const_inputs(graph, FakeQuantize, {3: float_array(output_low_value), - 4: float_array(output_high_value)}, - {'levels': 256, 'name': node_name + '/FakeQuantize'}) - node.in_port(0).get_connection().set_destination(fake_quantize.in_port(0)) - - # Calculate input_low value - mul_low = create_op_with_const_inputs(graph, Mul, {1: float_array(output_low_value - zerop.value)}, - {'name': node_name + '/Mul/Low'}) - node.in_port(1).get_connection().set_destination(mul_low.in_port(0)) - mul_low.out_port(0).connect(fake_quantize.in_port(1)) - - # Calculate input_high value - mul_high = create_op_with_const_inputs(graph, Mul, {1: float_array(output_high_value - zerop.value)}, - {'name': node_name + '/Mul/High'}) - mul_low.in_port(0).get_connection().add_destination(mul_high.in_port(0)) - mul_high.out_port(0).connect(fake_quantize.in_port(2)) - - cast = Cast(graph, {'dst_type': zero_point_type, 'name': node_name + '/Cast'}).create_node() - rename_nodes([(node, node_name + '/TBD'), (cast, node_name)]) - fake_quantize.out_port(0).connect(cast.in_port(0)) - - return [cast.id] diff --git a/model-optimizer/extensions/middle/dequantize_linear_resolver.py b/model-optimizer/extensions/middle/dequantize_linear_resolver.py new file mode 100644 index 00000000000..5ec93847512 --- /dev/null +++ b/model-optimizer/extensions/middle/dequantize_linear_resolver.py @@ -0,0 +1,66 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import numpy as np + +from extensions.ops.Cast import Cast +from extensions.ops.elementwise import Mul, Sub +from mo.front.common.partial_infer.utils import int64_array +from mo.front.tf.graph_utils import create_op_with_const_inputs +from mo.graph.graph import Graph, rename_nodes +from mo.middle.passes.convert_data_type import data_type_str_to_np +from mo.middle.replacement import MiddleReplacementPattern +from mo.ops.reshape import Reshape + + +class DequantizeLinearResolver(MiddleReplacementPattern): + """ + Transformation result depends on the axis value. + If the axis is not set or x_scale input is scalar or 1D tensor with one element then DequantizeLinear is + replaced with the sub-graph which can be expressed with the following formula: + y = (x - x_zero_point) * x_scale + In other cases DequantizeLinear can be replace to formula with addition reshape x_zero_point and x_scale. + Target shape for reshape depend on axis. + """ + enabled = True + graph_condition = [lambda graph: graph.graph['layout'] == 'NCHW'] + + def find_and_replace_pattern(self, graph: Graph): + for dequantize_node in graph.get_op_nodes(op='DequantizeLinear'): + node_name = dequantize_node.soft_get('name', dequantize_node.id) + axis = dequantize_node.soft_get('axis', None) + scale_y_shape = dequantize_node.in_port(1).data.get_shape() + model_data_type = data_type_str_to_np(graph.graph['cmd_params'].data_type) + cast = Cast(graph, {'dst_type': model_data_type, 'name': node_name + '/Cast'}).create_node() + dequantize_node.in_port(0).get_connection().set_destination(cast.in_port(0)) + mul = Mul(graph, {}).create_node() + + is_second_port_connected = dequantize_node.is_in_port_connected(2) + if is_second_port_connected: + sub = Sub(graph, {'name': node_name + '/Sub'}).create_node() + cast.out_port(0).connect(sub.in_port(0)) + dequantize_node.in_port(2).get_connection().set_destination(sub.in_port(1)) + sub.out_port(0).connect(mul.in_port(0)) + else: + cast.out_port(0).connect(mul.in_port(0)) + + dequantize_node.in_port(1).get_connection().set_destination(mul.in_port(1)) + dequantize_node.out_port(0).get_connection().set_source(mul.out_port(0)) + rename_nodes([(dequantize_node, node_name + '/TBD'), (mul, node_name)]) + + assert scale_y_shape is not None + if axis is not None and len(scale_y_shape) > 0 and scale_y_shape[0] > 1: + input_shape = cast.in_port(0).data.get_shape() + target_shape = np.ones(len(input_shape), np.int64) + target_shape[axis] = input_shape[axis] + + mul_reshape = create_op_with_const_inputs(graph, Reshape, {1: int64_array(target_shape)}, + {'name': node_name + '/Reshape/Mul'}) + mul.in_port(1).get_connection().set_destination(mul_reshape.in_port(0)) + mul_reshape.out_port(0).connect(mul.in_port(1)) + + if is_second_port_connected: + sub_reshape = create_op_with_const_inputs(graph, Reshape, {1: int64_array(target_shape)}, + {'name': node_name + '/Reshape/Sub'}) + sub.in_port(1).get_connection().set_destination(sub_reshape.in_port(0)) + sub_reshape.out_port(0).connect(sub.in_port(1)) diff --git a/model-optimizer/extensions/middle/quantize_fuses.py b/model-optimizer/extensions/middle/quantize_fuses.py index 2db975333c1..bafad08c3cc 100644 --- a/model-optimizer/extensions/middle/quantize_fuses.py +++ b/model-optimizer/extensions/middle/quantize_fuses.py @@ -6,6 +6,7 @@ import numpy as np from extensions.middle.BinarizeWeightsM1P1 import BinarizeWeightsM1P1 from extensions.middle.DeleteControlFlowEdges import DeleteControlFlowEdges from extensions.middle.EltwiseChecker import EltwiseChecker +from extensions.middle.quantize_linear_resolver import QuantizeLinearResolver from mo.graph.graph import Graph from mo.middle.passes.fusing.helpers import get_value_in_port from mo.middle.replacement import MiddleReplacementPattern @@ -75,7 +76,7 @@ class FakeQuantizeFuse(MiddleReplacementPattern): graph_condition = [lambda graph: not graph.graph['cmd_params'].disable_fusing] def run_after(self): - return [MarkNodesToFuseUpToFakeQuantize] + return [QuantizeLinearResolver] def run_before(self): return [BinarizeWeightsM1P1] diff --git a/model-optimizer/extensions/middle/quantize_linear_resolver.py b/model-optimizer/extensions/middle/quantize_linear_resolver.py new file mode 100644 index 00000000000..3499ecb251f --- /dev/null +++ b/model-optimizer/extensions/middle/quantize_linear_resolver.py @@ -0,0 +1,101 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import numpy as np + +from extensions.ops.Cast import Cast +from extensions.ops.elementwise import Mul +from extensions.ops.fakequantize import FakeQuantize +from mo.front.common.partial_infer.utils import float_array, int64_array +from mo.front.tf.graph_utils import create_op_with_const_inputs +from mo.graph.graph import Graph, rename_nodes +from mo.middle.replacement import MiddleReplacementPattern +from mo.ops.const import Const +from mo.ops.reshape import Reshape +from mo.utils.error import Error + + +class QuantizeLinearResolver(MiddleReplacementPattern): + """ + Replaces QuantizeLinear with FakeQuantize + Transformation result depends on the axis value. + If the axis is not set or x_scale input is scalar or 1D tensor with one element then QuantizeLinear is + replaced with the sub-graph which can be expressed with the following formula: + QuantizeLinear -> FakeQuantize(input + Mul(y_scale, Const(low_value)) + Mul(y_scale, Const(high_value)) + Const(low_value) + Const(high_value)) + low_value and high_value depend on from y_zero_point type + In other cases y_scale and y_zero_point can be transform with addition reshape. + Target shape for y_scale and y_zero_point depend on axis value. + """ + enabled = True + graph_condition = [lambda graph: graph.graph['layout'] == 'NCHW'] + + def run_after(self): + from extensions.middle.quantize_fuses import MarkNodesToFuseUpToFakeQuantize + return [MarkNodesToFuseUpToFakeQuantize] + + def find_and_replace_pattern(self, graph: Graph): + for quantize_node in graph.get_op_nodes(op='QuantizeLinear'): + node_name = quantize_node.soft_get('name', quantize_node.id) + axis = quantize_node.soft_get('axis', None) + scale_y_shape = quantize_node.in_port(1).data.get_shape() + + if quantize_node.is_in_port_connected(2): + zerop = quantize_node.in_port(2).get_source().node + else: + zerop = Const(graph, + {'value': np.array(0, dtype=np.uint8), 'name': node_name + '/ZeroPoint'}).create_node() + + assert zerop.soft_get('type') == 'Const', 'only constant for zero_point is supported for QuantizeLinear' + zero_point_type = zerop.value.dtype + # data type affects range of output values: [-128..127] or [0..255] + if zero_point_type == np.int8: + output_low_value = -128.0 + output_high_value = 127.0 + elif zero_point_type == np.uint8: + output_low_value = 0.0 + output_high_value = 255.0 + else: + raise Error('Not expected type {} for zero point value in node {}'.format( + zero_point_type, zerop.soft_get('name'))) + + fake_quantize = create_op_with_const_inputs(graph, FakeQuantize, {3: float_array(output_low_value), + 4: float_array(output_high_value)}, + {'levels': 256, 'name': node_name + '/FakeQuantize'}) + quantize_node.in_port(0).get_connection().set_destination(fake_quantize.in_port(0)) + + # Calculate input_low value + mul_low = create_op_with_const_inputs(graph, Mul, {1: float_array(output_low_value - zerop.value)}, + {'name': node_name + '/Mul/Low'}) + quantize_node.in_port(1).get_connection().set_destination(mul_low.in_port(0)) + mul_low.out_port(0).connect(fake_quantize.in_port(1)) + + # Calculate input_high value + mul_high = create_op_with_const_inputs(graph, Mul, {1: float_array(output_high_value - zerop.value)}, + {'name': node_name + '/Mul/High'}) + mul_low.in_port(0).get_connection().add_destination(mul_high.in_port(0)) + mul_high.out_port(0).connect(fake_quantize.in_port(2)) + + cast = Cast(graph, {'dst_type': zero_point_type, 'name': node_name + '/Cast'}).create_node() + fake_quantize.out_port(0).connect(cast.in_port(0)) + quantize_node.out_port(0).get_connection().set_source(cast.out_port(0)) + rename_nodes([(quantize_node, node_name + '/TBD'), (cast, node_name)]) + + assert scale_y_shape is not None + if axis is not None and len(scale_y_shape) > 0 and scale_y_shape[0] > 1: + input_shape = fake_quantize.in_port(0).data.get_shape() + target_shape = np.ones(len(input_shape), np.int) + target_shape[axis] = input_shape[axis] + mul_low_reshape = create_op_with_const_inputs(graph, Reshape, {1: int64_array(target_shape)}, + {'name': node_name + '/Reshape/Mul/Low'}) + mul_high_reshape = create_op_with_const_inputs(graph, Reshape, {1: int64_array(target_shape)}, + {'name': node_name + '/Reshape/Mul/high'}) + + fake_quantize.in_port(1).get_connection().set_destination(mul_low_reshape.in_port(0)) + fake_quantize.in_port(2).get_connection().set_destination(mul_high_reshape.in_port(0)) + + mul_low_reshape.out_port(0).connect(fake_quantize.in_port(1)) + mul_high_reshape.out_port(0).connect(fake_quantize.in_port(2)) diff --git a/model-optimizer/extensions/ops/dequantize_linear.py b/model-optimizer/extensions/ops/dequantize_linear.py index ec4fc70ac9d..84c6c050611 100644 --- a/model-optimizer/extensions/ops/dequantize_linear.py +++ b/model-optimizer/extensions/ops/dequantize_linear.py @@ -1,6 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +from mo.front.common.partial_infer.elemental import copy_shape_infer from mo.graph.graph import Graph from mo.ops.op import Op @@ -13,8 +14,9 @@ class DequantizeLinear(Op): mandatory_props = { 'type': None, 'op': self.op, + 'axis': None, 'version': None, - 'infer': None, + 'infer': copy_shape_infer, 'out_ports_count': 1, 'in_ports_count': 3, } diff --git a/model-optimizer/extensions/ops/quantize_linear.py b/model-optimizer/extensions/ops/quantize_linear.py index 7068ee42de9..dcad25acbed 100644 --- a/model-optimizer/extensions/ops/quantize_linear.py +++ b/model-optimizer/extensions/ops/quantize_linear.py @@ -1,6 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +from mo.front.common.partial_infer.elemental import copy_shape_infer from mo.graph.graph import Graph from mo.ops.op import Op @@ -13,8 +14,9 @@ class QuantizeLinear(Op): mandatory_props = { 'type': None, 'op': self.op, + 'axis': None, 'version': None, - 'infer': None, + 'infer': copy_shape_infer, 'out_ports_count': 1, 'in_ports_count': 3, } diff --git a/model-optimizer/mo/ops/broadcast.py b/model-optimizer/mo/ops/broadcast.py index 0edd867bb29..793d2b49102 100644 --- a/model-optimizer/mo/ops/broadcast.py +++ b/model-optimizer/mo/ops/broadcast.py @@ -58,8 +58,8 @@ class Broadcast(Op): node.out_port(0).data.set_value(bi_directional_broadcasting(input_value, target_shape)) elif node.mode == 'explicit': axes_mapping = node.in_port(2).data.get_value() - assert axes_mapping is not None, 'Broadcast(mode="explicit") with dynamic axes_mapping input ' \ - 'is not supported. Node: `{}`'.format(node_name) + assert axes_mapping is not None, 'Broadcast(mode="explicit") with dynamic axes_mapping input ' \ + 'is not supported. Node: `{}`'.format(node_name) PermuteInputs().set_input_permutation(node.in_node(2), node, 'output:0', 'axis') axes_mapping = node.in_port(2).data.get_value() node.out_port(0).data.set_value(explicit_broadcasting(input_value, target_shape, axes_mapping)) diff --git a/model-optimizer/unit_tests/extensions/front/onnx/dequantize_linear_resolver_test.py b/model-optimizer/unit_tests/extensions/front/onnx/dequantize_linear_resolver_test.py deleted file mode 100644 index c305ec57ca3..00000000000 --- a/model-optimizer/unit_tests/extensions/front/onnx/dequantize_linear_resolver_test.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -import numpy as np - -from extensions.front.onnx.dequantize_linear_resolver import DequantizeLinearResolver -from mo.utils.ir_engine.compare_graphs import compare_graphs -from unit_tests.utils.graph import build_graph - -nodes1_attributes = { - 'input': {'kind': 'op', 'op': 'AnyOp'}, - 'dequantize': {'kind': 'op', 'op': 'DequantizeLinear'}, - 'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'out': {'kind': 'op', 'op': 'AnyOp'}, -} - -nodes_ref_attributes = { - 'input': {'kind': 'op', 'op': 'AnyOp'}, - 'cast': {'kind': 'op', 'op': 'Cast', 'type': 'Convert'}, - 'sub': {'kind': 'op', 'op': 'Sub', 'type': 'Subtract'}, - 'mul': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'}, - 'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'out': {'kind': 'op', 'op': 'AnyOp'}, -} - - -class TestDequantizeLinearResolver(unittest.TestCase): - - def test_dequantize(self): - graph = build_graph(nodes1_attributes, - [('input', 'dequantize'), - ('scale_param_dq', 'dequantize'), - ('zerop_param_dq', 'dequantize'), - ('dequantize', 'out'), - ], - {'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, - 'zerop_param_dq': {'shape': np.array([]), 'value': np.uint8(0)}, - }, nodes_with_edges_only=True) - - graph_ref = build_graph(nodes_ref_attributes, - [('input', 'cast'), - ('cast', 'sub'), - ('zerop_param_dq', 'sub'), - ('sub', 'mul'), - ('scale_param_dq', 'mul'), - ('mul', 'out'), - ], - {'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, - 'zerop_param_dq': {'shape': np.array([]), 'value': np.uint8(0)} - }, nodes_with_edges_only=True) - - graph.stage = 'front' - DequantizeLinearResolver().find_and_replace_pattern(graph) - - (flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True) - self.assertTrue(flag, resp) - - def test_dequantize_no_zerop(self): - graph = build_graph(nodes1_attributes, - [('input', 'dequantize'), - ('scale_param_dq', 'dequantize'), - ('dequantize', 'out'), - ], - {'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, - }, nodes_with_edges_only=True) - - graph_ref = build_graph(nodes_ref_attributes, - [('input', 'cast'), - ('cast', 'mul'), - ('scale_param_dq', 'mul'), - ('mul', 'out'), - ], - {'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)} - }, nodes_with_edges_only=True) - - graph.stage = 'front' - DequantizeLinearResolver().find_and_replace_pattern(graph) - - (flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True) - self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/front/onnx/quantize_linear_resolver_test.py b/model-optimizer/unit_tests/extensions/front/onnx/quantize_linear_resolver_test.py deleted file mode 100644 index 2209f87e0d4..00000000000 --- a/model-optimizer/unit_tests/extensions/front/onnx/quantize_linear_resolver_test.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -import numpy as np - -from extensions.front.onnx.quantize_linear_resolver import QuantizeLinearResolver -from mo.utils.ir_engine.compare_graphs import compare_graphs -from unit_tests.utils.graph import build_graph - -nodes1_attributes = { - 'input': {'kind': 'op', 'op': 'AnyOp'}, - 'quantize': {'kind': 'op', 'op': 'QuantizeLinear'}, - 'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'zerop_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'out': {'kind': 'op', 'op': 'AnyOp'}, -} - -nodes_ref_attributes = { - 'input': {'kind': 'op', 'op': 'AnyOp'}, - 'cast': {'kind': 'op', 'op': 'Cast', 'type': 'Convert'}, - 'f_quantize': {'kind': 'op', 'op': 'FakeQuantize', 'type': 'FakeQuantize'}, - 'mul1': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'}, - 'mul2': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'}, - 'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'in_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'in_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'out_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'out_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, - 'out': {'kind': 'op', 'op': 'AnyOp'}, -} - - -class TestQuantizeLinearResolver(unittest.TestCase): - - def test_quantize_uint8(self): - graph = build_graph(nodes1_attributes, - [('input', 'quantize'), - ('scale_param_q', 'quantize'), - ('zerop_param_q', 'quantize'), - ('quantize', 'out'), - ], - {'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, - 'zerop_param_q': {'shape': np.array([]), 'value': np.uint8(128)}, - }, nodes_with_edges_only=True) - - graph_ref = build_graph(nodes_ref_attributes, - [('input', 'f_quantize'), - ('scale_param_q', 'mul1', {'out': 0}), - ('in_low', 'mul1'), - ('mul1', 'f_quantize'), - ('scale_param_q', 'mul2', {'out': 0}), - ('in_high', 'mul2'), - ('mul2', 'f_quantize'), - ('out_low', 'f_quantize'), - ('out_high', 'f_quantize'), - ('f_quantize', 'cast'), - ('cast', 'out'), - ], - {'in_low': {'shape': np.array([]), 'value': -128}, - 'in_high': {'shape': np.array([]), 'value': 127}, - 'out_low': {'shape': np.array([]), 'value': 0}, - 'out_high': {'shape': np.array([]), 'value': 255}, - 'cast': {'dst_type': np.uint8} - }, nodes_with_edges_only=True) - - graph.stage = 'front' - QuantizeLinearResolver().find_and_replace_pattern(graph) - - (flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True) - self.assertTrue(flag, resp) - - def test_quantize_int8(self): - graph = build_graph(nodes1_attributes, - [('input', 'quantize'), - ('scale_param_q', 'quantize'), - ('zerop_param_q', 'quantize'), - ('quantize', 'out'), - ], - {'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, - 'zerop_param_q': {'shape': np.array([]), 'value': np.int8(0)}, - }, nodes_with_edges_only=True) - - graph_ref = build_graph(nodes_ref_attributes, - [('input', 'f_quantize'), - ('scale_param_q', 'mul1', {'out': 0}), - ('in_low', 'mul1'), - ('mul1', 'f_quantize'), - ('scale_param_q', 'mul2', {'out': 0}), - ('in_high', 'mul2'), - ('mul2', 'f_quantize'), - ('out_low', 'f_quantize'), - ('out_high', 'f_quantize'), - ('f_quantize', 'cast'), - ('cast', 'out'), - ], - {'in_low': {'shape': np.array([]), 'value': -128}, - 'in_high': {'shape': np.array([]), 'value': 127}, - 'out_low': {'shape': np.array([]), 'value': -128}, - 'out_high': {'shape': np.array([]), 'value': 127}, - 'cast': {'dst_type': np.int8} - }, nodes_with_edges_only=True) - - graph.stage = 'front' - QuantizeLinearResolver().find_and_replace_pattern(graph) - - (flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True) - self.assertTrue(flag, resp) - - def test_quantize_no_zerop(self): - graph = build_graph(nodes1_attributes, - [('input', 'quantize'), - ('scale_param_q', 'quantize'), - ('quantize', 'out'), - ], - {'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, - }, nodes_with_edges_only=True) - - graph_ref = build_graph(nodes_ref_attributes, - [('input', 'f_quantize'), - ('scale_param_q', 'mul1', {'out': 0}), - ('in_low', 'mul1'), - ('mul1', 'f_quantize'), - ('scale_param_q', 'mul2', {'out': 0}), - ('in_high', 'mul2'), - ('mul2', 'f_quantize'), - ('out_low', 'f_quantize'), - ('out_high', 'f_quantize'), - ('f_quantize', 'cast'), - ('cast', 'out'), - ], - {'in_low': {'shape': np.array([]), 'value': 0}, - 'in_high': {'shape': np.array([]), 'value': 255}, - 'out_low': {'shape': np.array([]), 'value': 0}, - 'out_high': {'shape': np.array([]), 'value': 255}, - 'cast': {'dst_type': np.uint8} - }, nodes_with_edges_only=True) - - graph.stage = 'front' - QuantizeLinearResolver().find_and_replace_pattern(graph) - - (flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True) - self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/middle/dequantize_linear_resolver_test.py b/model-optimizer/unit_tests/extensions/middle/dequantize_linear_resolver_test.py new file mode 100644 index 00000000000..4e4fef50743 --- /dev/null +++ b/model-optimizer/unit_tests/extensions/middle/dequantize_linear_resolver_test.py @@ -0,0 +1,237 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +import numpy as np + +from extensions.middle.dequantize_linear_resolver import DequantizeLinearResolver +from mo.front.common.partial_infer.utils import int64_array +from mo.utils.ir_engine.compare_graphs import compare_graphs +from unit_tests.utils.graph import build_graph +from generator import generator, generate + +nodes1_attributes = { + 'input': {'kind': 'op', 'op': 'AnyOp'}, + 'input_data': {'kind': 'data', 'shape': None}, + 'dequantize': {'kind': 'op', 'op': 'DequantizeLinear', 'axis': 1}, + 'dequantize_data': {'kind': 'data', 'shape': None}, + 'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'scale_param_dq_data': {'kind': 'data', 'shape': None}, + 'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'zerop_param_dq_data': {'kind': 'data', 'shape': None}, + 'out': {'kind': 'op', 'op': 'AnyOp'}, + 'out_data': {'kind': 'data', 'shape': None}, + 'result': {'kind': 'op', 'op': 'Result'}, +} + +nodes_ref_attributes = { + 'input': {'kind': 'op', 'op': 'AnyOp'}, + 'input_data': {'kind': 'data', 'shape': None}, + 'cast': {'kind': 'op', 'op': 'Cast', 'type': 'Convert'}, + 'cast_data': {'kind': 'data', 'shape': None}, + 'sub': {'kind': 'op', 'op': 'Sub', 'type': 'Subtract'}, + 'sub_data': {'kind': 'data', 'shape': None}, + 'mul': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'}, + 'mul_data': {'kind': 'data', 'shape': None}, + 'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'scale_param_dq_data': {'kind': 'data', 'shape': None}, + 'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'zerop_param_dq_data': {'kind': 'data', 'shape': None}, + 'out': {'kind': 'op', 'op': 'AnyOp'}, + 'out_data': {'kind': 'data', 'shape': None}, + 'result': {'kind': 'op', 'op': 'Result'}, + + 'sub_reshape_const': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'sub_reshape_const_data': {'kind': 'data', 'shape': None}, + 'sub_reshape': {'kind': 'op', 'type': 'Reshape', 'op': 'Reshape'}, + 'sub_reshape_data': {'kind': 'data', 'shape': None}, + + 'mul_reshape_const': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'mul_reshape_const_data': {'kind': 'data', 'shape': None}, + 'mul_reshape': {'kind': 'op', 'type': 'Reshape', 'op': 'Reshape'}, + 'mul_reshape_data': {'kind': 'data', 'shape': None}, +} + + +class TestDequantizeLinearResolver(unittest.TestCase): + + def test_dequantize(self): + graph = build_graph(nodes1_attributes, + [('input', 'input_data'), + ('input_data', 'dequantize'), + ('dequantize', 'dequantize_data'), + ('scale_param_dq', 'scale_param_dq_data'), + ('zerop_param_dq', 'zerop_param_dq_data'), + ('scale_param_dq_data', 'dequantize'), + ('zerop_param_dq_data', 'dequantize'), + ('dequantize_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'input_data': {'shape': int64_array([1, 3, 224, 224])}, + 'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'scale_param_dq_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'zerop_param_dq': {'shape': np.array([]), 'value': np.uint8(0)}, + 'zerop_param_dq_data': {'shape': np.array([]), 'value': np.uint8(0)}, + }, nodes_with_edges_only=True) + + graph_ref = build_graph(nodes_ref_attributes, + [('input', 'input_data'), + ('input_data', 'cast'), + ('cast', 'cast_data'), + ('cast_data', 'sub'), + ('zerop_param_dq', 'zerop_param_dq_data'), + ('zerop_param_dq_data', 'sub'), + ('sub', 'sub_data'), + ('sub_data', 'mul'), + ('scale_param_dq', 'scale_param_dq_data'), + ('scale_param_dq_data', 'mul'), + ('mul', 'mul_data'), + ('mul_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'input_data': {'shape': int64_array([1, 3, 224, 224])}, + 'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'scale_param_dq_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'zerop_param_dq': {'shape': np.array([]), 'value': np.uint8(0)}, + 'zerop_param_dq_data': {'shape': np.array([]), 'value': np.uint8(0)}, + }, nodes_with_edges_only=True) + + graph.stage = 'middle' + DequantizeLinearResolver().find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_dequantize_no_zerop(self): + graph = build_graph(nodes1_attributes, + [('input', 'input_data'), + ('input_data', 'dequantize'), + ('dequantize', 'dequantize_data'), + ('scale_param_dq', 'scale_param_dq_data'), + ('scale_param_dq_data', 'dequantize'), + ('dequantize', 'dequantize_data'), + ('dequantize_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'input_data': {'shape': int64_array([1, 3, 224, 224])}, + 'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'scale_param_dq_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + }, nodes_with_edges_only=True) + + graph_ref = build_graph(nodes_ref_attributes, + [('input', 'input_data'), + ('input_data', 'cast'), + ('cast', 'cast_data'), + ('cast_data', 'mul'), + ('scale_param_dq', 'scale_param_dq_data'), + ('scale_param_dq_data', 'mul'), + ('mul', 'mul_data'), + ('mul_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'input_data': {'shape': int64_array([1, 3, 224, 224])}, + 'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'scale_param_dq_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + }, nodes_with_edges_only=True) + + graph.stage = 'middle' + DequantizeLinearResolver().find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True) + self.assertTrue(flag, resp) + +@generator +class TestDequantizeWithAxis(unittest.TestCase): + @generate(*[(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 4, 1]), 2), + (int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 3, 1, 1]), 1), + (int64_array([2, 3, 4, 4]), int64_array([2, 3, 4, 5]), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([2, 1, 1, 1]), 0), + (int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 4, 1]), -2), + (int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 1, 4]), -1), + (int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]), + np.array([2, 3, 4, 5], dtype=np.int32), int64_array([1, 1, 4, 1]), 2), + (int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]), + np.array([2, 3, 4, 5], dtype=np.int32), int64_array([1, 3, 1, 1]), 1), + (int64_array([2, 3, 4, 4]), int64_array([2, 3, 4, 5]), + np.array([2, 3, 4, 5], dtype=np.int32), int64_array([2, 1, 1, 1]), 0), + ]) + def test_dequantize_with_axis(self, input_shape, scale_param_value, zero_param_value, target_shape, axis): + graph = build_graph(nodes1_attributes, + [('input', 'input_data'), + ('input_data', 'dequantize'), + ('dequantize', 'dequantize_data'), + ('scale_param_dq', 'scale_param_dq_data'), + ('zerop_param_dq', 'zerop_param_dq_data'), + ('scale_param_dq_data', 'dequantize'), + ('zerop_param_dq_data', 'dequantize'), + ('dequantize_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'input_data': {'shape': input_shape}, + 'dequantize': {'axis': axis}, + 'scale_param_dq': {'shape': scale_param_value.shape, + 'value': scale_param_value}, + 'scale_param_dq_data': {'shape': scale_param_value.shape, + 'value': scale_param_value}, + 'zerop_param_dq': {'shape': zero_param_value.shape, + 'value': zero_param_value}, + 'zerop_param_dq_data': {'shape': zero_param_value.shape, + 'value': zero_param_value}, + }, nodes_with_edges_only=True) + + graph_ref = build_graph(nodes_ref_attributes, + [('input', 'input_data'), + ('input_data', 'cast'), + ('cast', 'cast_data'), + ('cast_data', 'sub'), + ('zerop_param_dq', 'zerop_param_dq_data'), + + ('zerop_param_dq_data', 'sub_reshape'), + ('sub_reshape_const', 'sub_reshape_const_data'), + ('sub_reshape_const_data', 'sub_reshape'), + ('sub_reshape', 'sub_reshape_data'), + ('sub_reshape_data', 'sub'), + + ('sub', 'sub_data'), + ('sub_data', 'mul'), + ('scale_param_dq', 'scale_param_dq_data'), + + ('scale_param_dq_data', 'mul_reshape'), + ('mul_reshape_const', 'mul_reshape_const_data'), + ('mul_reshape_const_data', 'mul_reshape'), + ('mul_reshape', 'mul_reshape_data'), + ('mul_reshape_data', 'mul'), + + ('mul', 'mul_data'), + ('mul_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'input_data': {'shape': input_shape}, + 'scale_param_dq': {'shape': scale_param_value.shape, + 'value': scale_param_value}, + 'scale_param_dq_data': {'shape': scale_param_value.shape, + 'value': scale_param_value}, + 'zerop_param_dq': {'shape': zero_param_value.shape, + 'value': zero_param_value}, + 'zerop_param_dq_data': {'shape': zero_param_value.shape, + 'value': zero_param_value}, + 'sub_reshape_const_data': {'shape': target_shape.shape, 'value': target_shape}, + 'mul_reshape_const_data': {'shape': target_shape.shape, 'value': target_shape}, + }, nodes_with_edges_only=True) + + graph.stage = 'middle' + DequantizeLinearResolver().find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True) + self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/middle/quantize_linear_resolver_test.py b/model-optimizer/unit_tests/extensions/middle/quantize_linear_resolver_test.py new file mode 100644 index 00000000000..59431a905ef --- /dev/null +++ b/model-optimizer/unit_tests/extensions/middle/quantize_linear_resolver_test.py @@ -0,0 +1,369 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +import numpy as np + +from extensions.middle.quantize_linear_resolver import QuantizeLinearResolver +from mo.front.common.partial_infer.utils import int64_array +from mo.utils.ir_engine.compare_graphs import compare_graphs +from unit_tests.utils.graph import build_graph +from generator import generator, generate + +nodes1_attributes = { + 'input': {'kind': 'op', 'op': 'AnyOp'}, + 'input_data': {'kind': 'data', 'shape': None}, + 'quantize': {'kind': 'op', 'op': 'QuantizeLinear', 'axis': 1}, + 'quantize_data': {'kind': 'data', 'shape': None}, + 'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'scale_param_q_data': {'kind': 'data', 'shape': None}, + 'zerop_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'zerop_param_q_data': {'kind': 'data', 'shape': None}, + 'out': {'kind': 'op', 'op': 'AnyOp'}, + 'out_data': {'kind': 'data', 'shape': None}, + 'result': {'kind': 'op', 'op': 'Result'}, +} + +nodes_ref_attributes = { + 'input': {'kind': 'op', 'op': 'AnyOp'}, + 'input_data': {'kind': 'data', 'shape': None}, + 'cast': {'kind': 'op', 'op': 'Cast', 'type': 'Convert'}, + 'cast_data': {'kind': 'data', 'shape': None}, + 'f_quantize': {'kind': 'op', 'op': 'FakeQuantize', 'type': 'FakeQuantize'}, + 'f_quantize_data': {'kind': 'data', 'shape': None}, + 'mul1': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'}, + 'mul1_data': {'kind': 'data', 'shape': None}, + 'mul2': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'}, + 'mul2_data': {'kind': 'data', 'shape': None}, + 'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'scale_param_q_data': {'kind': 'data', 'shape': None}, + 'in_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'in_low_data': {'kind': 'data', 'shape': None}, + 'in_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'in_high_data': {'kind': 'data', 'shape': None}, + 'out_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'out_low_data': {'kind': 'data', 'shape': None}, + 'out_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'out_high_data': {'kind': 'data', 'shape': None}, + 'out': {'kind': 'op', 'op': 'AnyOp'}, + 'out_data': {'kind': 'data', 'shape': None}, + 'result': {'kind': 'op', 'op': 'Result'}, + + 'high_reshape_const': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'high_reshape_const_data': {'kind': 'data', 'shape': None}, + 'high_reshape': {'kind': 'op', 'type': 'Reshape', 'op': 'Reshape'}, + 'high_reshape_data': {'kind': 'data', 'shape': None}, + + 'low_reshape_const': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, + 'low_reshape_const_data': {'kind': 'data', 'shape': None}, + 'low_reshape': {'kind': 'op', 'type': 'Reshape', 'op': 'Reshape'}, + 'low_reshape_data': {'kind': 'data', 'shape': None}, +} + + +class TestQuantizeLinearResolver(unittest.TestCase): + + def test_quantize_uint8(self): + graph = build_graph(nodes1_attributes, + [('input', 'input_data'), + ('input_data', 'quantize'), + ('scale_param_q', 'scale_param_q_data'), + ('scale_param_q_data', 'quantize'), + ('zerop_param_q', 'zerop_param_q_data'), + ('zerop_param_q_data', 'quantize'), + ('quantize', 'quantize_data'), + ('quantize_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + { + 'quantize': {'axis': 2}, + 'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'scale_param_q_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'zerop_param_q': {'shape': np.array([]), 'value': np.uint8(128)}, + 'zerop_param_q_data': {'shape': np.array([]), 'value': np.uint8(128)}, + }, nodes_with_edges_only=True) + + graph_ref = build_graph(nodes_ref_attributes, + [('input', 'input_data'), + ('input_data', 'f_quantize'), + ('scale_param_q', 'scale_param_q_data'), + ('scale_param_q_data', 'mul1', {'out': 0}), + ('in_low', 'in_low_data'), + ('in_low_data', 'mul1'), + ('mul1', 'mul1_data'), + ('mul1_data', 'f_quantize'), + ('f_quantize', 'f_quantize_data'), + ('scale_param_q_data', 'mul2', {'out': 0}), + ('in_high', 'in_high_data'), + ('in_high_data', 'mul2'), + ('mul2', 'mul2_data'), + ('mul2_data', 'f_quantize'), + ('out_low', 'out_low_data'), + ('out_low_data', 'f_quantize'), + ('out_high', 'out_high_data'), + ('out_high_data', 'f_quantize'), + ('f_quantize_data', 'cast'), + ('cast', 'cast_data'), + ('cast_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'in_low': {'shape': np.array([]), 'value': -128}, + 'in_low_data': {'shape': np.array([]), 'value': -128}, + 'in_high': {'shape': np.array([]), 'value': 127}, + 'in_high_data': {'shape': np.array([]), 'value': 127}, + 'out_low': {'shape': np.array([]), 'value': 0}, + 'out_low_data': {'shape': np.array([]), 'value': 0}, + 'out_high': {'shape': np.array([]), 'value': 255}, + 'out_high_data': {'shape': np.array([]), 'value': 255}, + 'cast': {'dst_type': np.uint8} + }, nodes_with_edges_only=True) + + graph.stage = 'middle' + QuantizeLinearResolver().find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_quantize_int8(self): + graph = build_graph(nodes1_attributes, + [('input', 'input_data'), + ('input_data', 'quantize'), + ('scale_param_q', 'scale_param_q_data'), + ('scale_param_q_data', 'quantize'), + ('zerop_param_q', 'zerop_param_q_data'), + ('zerop_param_q_data', 'quantize'), + ('quantize', 'quantize_data'), + ('quantize_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'scale_param_q_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'zerop_param_q': {'shape': np.array([]), 'value': np.int8(0)}, + 'zerop_param_q_data': {'shape': np.array([]), 'value': np.int8(0)}, + }, nodes_with_edges_only=True) + + graph_ref = build_graph(nodes_ref_attributes, + [('input', 'input_data'), + ('input_data', 'f_quantize'), + ('scale_param_q', 'scale_param_q_data'), + ('scale_param_q_data', 'mul1', {'out': 0}), + ('in_low', 'in_low_data'), + ('in_low_data', 'mul1'), + ('mul1', 'mul1_data'), + ('mul1_data', 'f_quantize'), + ('f_quantize', 'f_quantize_data'), + ('scale_param_q_data', 'mul2', {'out': 0}), + ('in_high', 'in_high_data'), + ('in_high_data', 'mul2'), + ('mul2', 'mul2_data'), + ('mul2_data', 'f_quantize'), + ('out_low', 'out_low_data'), + ('out_low_data', 'f_quantize'), + ('out_high', 'out_high_data'), + ('out_high_data', 'f_quantize'), + ('f_quantize_data', 'cast'), + ('cast', 'cast_data'), + ('cast_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'in_low': {'shape': np.array([]), 'value': -128}, + 'in_low_data': {'shape': np.array([]), 'value': -128}, + 'in_high': {'shape': np.array([]), 'value': 127}, + 'in_high_data': {'shape': np.array([]), 'value': 127}, + 'out_low': {'shape': np.array([]), 'value': -128}, + 'out_low_data': {'shape': np.array([]), 'value': -128}, + 'out_high': {'shape': np.array([]), 'value': 127}, + 'out_high_data': {'shape': np.array([]), 'value': 127}, + 'cast': {'dst_type': np.int8} + }, nodes_with_edges_only=True) + + graph.stage = 'middle' + QuantizeLinearResolver().find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_quantize_no_zerop(self): + graph = build_graph(nodes1_attributes, + [('input', 'input_data'), + ('input_data', 'quantize'), + ('quantize', 'quantize_data'), + ('scale_param_q', 'scale_param_q_data'), + ('scale_param_q_data', 'quantize'), + ('quantize', 'quantize_data'), + ('quantize_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + 'scale_param_q_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}, + }, nodes_with_edges_only=True) + + graph_ref = build_graph(nodes_ref_attributes, + [('input', 'input_data'), + ('input_data', 'f_quantize'), + ('scale_param_q', 'scale_param_q_data'), + ('scale_param_q_data', 'mul1', {'out': 0}), + ('in_low', 'in_low_data'), + ('in_low_data', 'mul1'), + ('mul1', 'mul1_data'), + ('mul1_data', 'f_quantize'), + ('f_quantize', 'f_quantize_data'), + ('scale_param_q_data', 'mul2', {'out': 0}), + ('in_high', 'in_high_data'), + ('in_high_data', 'mul2'), + ('mul2', 'mul2_data'), + ('mul2_data', 'f_quantize'), + ('out_low', 'out_low_data'), + ('out_low_data', 'f_quantize'), + ('out_high', 'out_high_data'), + ('out_high_data', 'f_quantize'), + ('f_quantize_data', 'cast'), + ('cast', 'cast_data'), + ('cast_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'in_low': {'shape': np.array([]), 'value': 0}, + 'in_low_data': {'shape': np.array([]), 'value': 0}, + 'in_high': {'shape': np.array([]), 'value': 255}, + 'in_high_data': {'shape': np.array([]), 'value': 255}, + 'out_low': {'shape': np.array([]), 'value': 0}, + 'out_low_data': {'shape': np.array([]), 'value': 0}, + 'out_high': {'shape': np.array([]), 'value': 255}, + 'out_high_data': {'shape': np.array([]), 'value': 255}, + 'cast': {'dst_type': np.uint8} + }, nodes_with_edges_only=True) + + graph.stage = 'middle' + QuantizeLinearResolver().find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) + + +@generator +class TestQuantizeWithAxis(unittest.TestCase): + @generate(*[(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 4, 1]), + np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]), + 0, 255, 2), + (int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 3, 1, 1]), + np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]), + 0, 255, 1), + (int64_array([2, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([2, 1, 1, 1]), + np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]), + 0, 255, 0), + (int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 1, 4]), + np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]), + 0, 255, -1), + (int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 4, 1]), + np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]), + 0, 255, -2), + (int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.int8), int64_array([1, 1, 4, 1]), + np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]), + -128.0, 127.0, 2), + (int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.int8), int64_array([1, 3, 1, 1]), + np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]), + -128.0, 127.0, 1), + (int64_array([2, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.int8), int64_array([2, 1, 1, 1]), + np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]), + -128.0, 127.0, 0), + (int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.int8), int64_array([1, 1, 1, 4]), + np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]), + -128.0, 127.0, -1), + (int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32), + np.array([2, 3, 4, 5], dtype=np.int8), int64_array([1, 1, 4, 1]), + np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]), + -128.0, 127.0, -2), + ]) + def test_quantize_with_axis(self, input_shape, scale_param_value, zero_param_value, + target_shape, in_low, in_high, out_low, out_high, axis): + graph = build_graph(nodes1_attributes, + [('input', 'input_data'), + ('input_data', 'quantize'), + ('scale_param_q', 'scale_param_q_data'), + ('scale_param_q_data', 'quantize'), + ('zerop_param_q', 'zerop_param_q_data'), + ('zerop_param_q_data', 'quantize'), + ('quantize', 'quantize_data'), + ('quantize_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + { + 'quantize': {'axis': axis}, + 'input': {'shape': input_shape}, + 'input_data': {'shape': input_shape}, + 'scale_param_q': {'shape': scale_param_value.shape, 'value': scale_param_value}, + 'scale_param_q_data': {'shape': scale_param_value.shape, 'value': scale_param_value}, + 'zerop_param_q': {'shape': zero_param_value.shape, 'value': zero_param_value}, + 'zerop_param_q_data': {'shape': zero_param_value.shape, 'value': zero_param_value}, + }, nodes_with_edges_only=True) + + graph_ref = build_graph(nodes_ref_attributes, + [('input', 'input_data'), + ('input_data', 'f_quantize'), + ('scale_param_q', 'scale_param_q_data'), + ('scale_param_q_data', 'mul1', {'out': 0}), + ('in_low', 'in_low_data'), + ('in_low_data', 'mul1'), + ('mul1', 'mul1_data'), + ('mul1_data', 'high_reshape'), + ('high_reshape_const', 'high_reshape_const_data'), + ('high_reshape_const_data', 'high_reshape'), + ('high_reshape', 'high_reshape_data'), + ('high_reshape_data', 'f_quantize'), + + ('f_quantize', 'f_quantize_data'), + ('scale_param_q_data', 'mul2', {'out': 0}), + ('in_high', 'in_high_data'), + ('in_high_data', 'mul2'), + ('mul2', 'mul2_data'), + ('mul2_data', 'low_reshape'), + ('low_reshape', 'low_reshape_data'), + ('low_reshape_data', 'f_quantize'), + ('low_reshape_const', 'low_reshape_const_data'), + ('low_reshape_const_data', 'low_reshape'), + ('out_low', 'out_low_data'), + ('out_low_data', 'f_quantize'), + + ('out_high', 'out_high_data'), + ('out_high_data', 'f_quantize'), + ('f_quantize_data', 'cast'), + ('cast', 'cast_data'), + ('cast_data', 'out'), + ('out', 'out_data'), + ('out_data', 'result'), + ], + {'in_low': {'shape': in_low.shape, 'value': in_low}, + 'in_low_data': {'shape': in_low.shape, 'value': in_low}, + 'in_high': {'shape': in_high.shape, 'value': in_high}, + 'in_high_data': {'shape': in_high.shape, 'value': in_high}, + 'out_low': {'shape': np.array([]), 'value': out_low}, + 'out_low_data': {'shape': np.array([]), 'value': out_low}, + 'out_high': {'shape': np.array([]), 'value': out_high}, + 'out_high_data': {'shape': np.array([]), 'value': out_high}, + 'cast': {'dst_type': zero_param_value.dtype}, + 'low_reshape_const_data': {'shape': target_shape.shape, 'value': target_shape}, + 'high_reshape_const_data': {'shape': target_shape.shape, 'value': target_shape}, + }, nodes_with_edges_only=True) + + graph.stage = 'middle' + QuantizeLinearResolver().find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) From 6dc343d745a532b7984d4c6f7d5a1cfc14d7cbbb Mon Sep 17 00:00:00 2001 From: Ivan Tikhonov Date: Mon, 17 May 2021 16:57:04 +0300 Subject: [PATCH 94/99] NGraph reference implementation for Memory (#4956) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Reference implementation for memory * memory reference implementation tests, fixes * new class Variable context * fix ngraph code style * add new evaluate method to ngraph::function * unordered_set instead of set in find_variables method * added a new Memory base class; automatiс memory allocation for Variable context in Assign ops; refactoring * ngraph codestyle * ngraph codestyle * temporary disable the check of variables in ngraph::function * fix for evaluate hides overloaded virtual function warning * ngraph codestyle * uncomment a check in validate_and_infer method * Removing a check (not backward compatible); adding docs * Auto detect Parameters/Variables, new constructors in ngraph::function * use zero initial values in ReadValue v6 evaluate * fix unit tests * fix codestyle * fix build (werror) * ngraph codestyle * update unit tests, refactoring * ngraph codestyle * refactoring, docs, new unit tests * Resolve review remarks * rt_attributes likeapproach in EvaluationContext, codestyle * fix build and unit tests * resolve review comments * resolve review comments * codestyle * export public API --- ngraph/core/include/ngraph/function.hpp | 75 ++++- ngraph/core/include/ngraph/node.hpp | 17 + ngraph/core/include/ngraph/op/assign.hpp | 33 +- ngraph/core/include/ngraph/op/read_value.hpp | 36 +- .../include/ngraph/op/util/broadcast_base.hpp | 7 +- .../core/include/ngraph/op/util/variable.hpp | 7 +- .../ngraph/op/util/variable_context.hpp | 100 ++++++ .../ngraph/op/util/variable_extension.hpp | 42 +++ .../include/ngraph/op/util/variable_value.hpp | 55 +++ .../core/include/ngraph/validation_util.hpp | 11 +- ngraph/core/src/function.cpp | 212 ++++++++++-- ngraph/core/src/node.cpp | 7 + ngraph/core/src/op/assign.cpp | 43 +++ ngraph/core/src/op/read_value.cpp | 38 +++ ngraph/core/src/op/result.cpp | 1 + ngraph/core/src/op/util/broadcast_base.cpp | 8 +- .../core/src/op/util/evaluation_context.cpp | 8 + ngraph/core/src/validation_util.cpp | 13 +- ngraph/test/CMakeLists.txt | 1 + ngraph/test/build_graph.cpp | 116 +++++++ ngraph/test/op_eval/memory.cpp | 316 ++++++++++++++++++ 21 files changed, 1049 insertions(+), 97 deletions(-) create mode 100644 ngraph/core/include/ngraph/op/util/variable_context.hpp create mode 100644 ngraph/core/include/ngraph/op/util/variable_extension.hpp create mode 100644 ngraph/core/include/ngraph/op/util/variable_value.hpp create mode 100644 ngraph/core/src/op/util/evaluation_context.cpp create mode 100644 ngraph/test/op_eval/memory.cpp diff --git a/ngraph/core/include/ngraph/function.hpp b/ngraph/core/include/ngraph/function.hpp index a48bc6ee665..6edd1d211f4 100644 --- a/ngraph/core/include/ngraph/function.hpp +++ b/ngraph/core/include/ngraph/function.hpp @@ -13,9 +13,12 @@ #include "ngraph/ngraph_visibility.hpp" #include "ngraph/node.hpp" +#include "ngraph/op/assign.hpp" #include "ngraph/op/parameter.hpp" +#include "ngraph/op/read_value.hpp" #include "ngraph/op/result.hpp" #include "ngraph/op/sink.hpp" +#include "ngraph/op/util/variable.hpp" namespace ngraph { @@ -51,7 +54,39 @@ namespace ngraph const ParameterVector& parameters, const std::string& name = ""); - virtual ~Function() {} + Function(const ResultVector& results, + const SinkVector& sinks, + const ParameterVector& parameters, + const VariableVector& variables, + const std::string& name = ""); + + Function(const OutputVector& results, + const SinkVector& sinks, + const ParameterVector& parameters, + const VariableVector& variables, + const std::string& name = ""); + + Function(const ResultVector& results, + const ParameterVector& parameters, + const VariableVector& variables, + const std::string& name = ""); + + Function(const OutputVector& results, + const ParameterVector& parameters, + const VariableVector& variables, + const std::string& name = ""); + + /// Constructs a Function. Lists of parameters and variables will be generated automatically + /// based on traversing the graph from the results. + explicit Function(const OutputVector& results, const std::string& name = ""); + + /// Constructs a Function. Lists of parameters and variables will be generated automatically + /// based on traversing the graph from the results and the sinks. + Function(const OutputVector& results, + const SinkVector& sinks, + const std::string& name = ""); + + virtual ~Function() = default; /// Return the number of outputs for this function. size_t get_output_size() const; @@ -132,10 +167,13 @@ namespace ngraph int64_t get_result_index(const Output& value) const; /// \brief Evaluate the function on inputs, putting results in outputs. - /// \param outputs Tensors for the outputs to compute. One for each result - /// \param inputs Tensors for the inputs. One for each inputs. + /// \param output_tensors Tensors for the outputs to compute. One for each result + /// \param input_tensors Tensors for the inputs. One for each inputs. + /// \param evaluation_context Storage of additional settings and attributes that can be used + /// when evaluating the function. This additional information can be shared across nodes. bool evaluate(const HostTensorVector& output_tensors, - const HostTensorVector& input_tensors) const; + const HostTensorVector& input_tensors, + EvaluationContext evaluation_context = EvaluationContext()) const; /// \brief Return a list of function's sinks. const SinkVector& get_sinks() const { return m_sinks; } @@ -185,12 +223,35 @@ namespace ngraph /// \param param Parameter node to delete void remove_parameter(const std::shared_ptr& param); + /// \brief Add new variables to the list. Method doesn't validate graph, it should be done + /// manually after all changes. + /// \param variables new variables to add + void add_variables(const VariableVector& variables); + + /// \brief Delete variable from the list of variables. + /// Method doesn't delete nodes that used this variable from the graph. + /// \param variable Variable to delete + void remove_variable(const VariablePtr& variable); + + /// \brief Return a list of function's variables. + const VariableVector& get_variables() const { return m_variables; } + + /// \brief Return a variable by specified variable_id. + VariablePtr get_variable_by_id(const std::string& variable_id) const; + private: Function(const Function&) = delete; Function(const Function&&) = delete; Function& operator=(const Function&) = delete; - /// \brief Checks all the Parameter nodes are registered in the list of Function parameters - void check_all_parameters_registered() const; + + /// \brief Depending on the options selected, + /// checks all the Parameter/Variables are registered in the list of Function + /// parameters/variables or finds all Parameters/Variables in a function and registers them. + /// \param detect_variables If this flag is true, then it finds all Variables in a function + /// and registers them, otherwise checks all the Variables are registered. + /// \param detect_parameters If this flag is true, then it finds all Parameters in a + /// function and registers them, otherwise checks all the Parameters are registered. + void prerequirements(bool detect_variables, bool detect_parameters); static std::atomic m_next_instance_id; std::string m_name; @@ -199,11 +260,11 @@ namespace ngraph topological_sort_t m_topological_sorter; ResultVector m_results; - // List of the nodes with side effect in graph. // These nodes are not outputs of graph but should not be removed even if have no children. SinkVector m_sinks; ParameterVector m_parameters; + VariableVector m_variables; }; template <> diff --git a/ngraph/core/include/ngraph/node.hpp b/ngraph/core/include/ngraph/node.hpp index b1eb4a3f6b7..e5830122128 100644 --- a/ngraph/core/include/ngraph/node.hpp +++ b/ngraph/core/include/ngraph/node.hpp @@ -30,6 +30,8 @@ #include "ngraph/node_output.hpp" #include "ngraph/op/util/attr_types.hpp" #include "ngraph/op/util/op_annotations.hpp" +#include "ngraph/op/util/variable.hpp" +#include "ngraph/op/util/variable_value.hpp" #include "ngraph/output_vector.hpp" #include "ngraph/strides.hpp" #include "ngraph/type.hpp" @@ -56,6 +58,10 @@ namespace ngraph using HostTensorPtr = std::shared_ptr; using HostTensorVector = std::vector; + /// EvaluationContext stores and manages a context (additional parameters, values and + /// environment) for evaluating ngraph::function. + using EvaluationContext = std::map>; + namespace op { struct AutoBroadcastSpec; @@ -194,9 +200,20 @@ namespace ngraph /// \returns the autobroadcasr spec virtual const op::AutoBroadcastSpec& get_autob() const; /// \brief Evaluates the op on input_values putting results in output_values + /// \param output_values Tensors for the outputs to compute. One for each result + /// \param input_values Tensors for the inputs. One for each inputs. /// \returns true if successful virtual bool evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const; + /// \brief Evaluates the op on input_values putting results in output_values + /// \param output_values Tensors for the outputs to compute. One for each result + /// \param input_values Tensors for the inputs. One for each inputs. + /// \param evaluation_context Storage of additional settings and attributes that can be used + /// when evaluating the op. + /// \returns true if successful + virtual bool evaluate(const HostTensorVector& output_values, + const HostTensorVector& input_values, + const EvaluationContext& evaluationContext) const; virtual bool evaluate_lower(const HostTensorVector& output_values) const; virtual bool evaluate_upper(const HostTensorVector& output_values) const; diff --git a/ngraph/core/include/ngraph/op/assign.hpp b/ngraph/core/include/ngraph/op/assign.hpp index cf801f22409..071f3d367a8 100644 --- a/ngraph/core/include/ngraph/op/assign.hpp +++ b/ngraph/core/include/ngraph/op/assign.hpp @@ -6,12 +6,13 @@ #include "ngraph/op/sink.hpp" #include "ngraph/op/util/variable.hpp" +#include "ngraph/op/util/variable_extension.hpp" namespace ngraph { namespace op { - class NGRAPH_API AssignBase : public Sink + class NGRAPH_API AssignBase : public Sink, public VariableExtension { public: NGRAPH_RTTI_DECLARATION; @@ -21,27 +22,6 @@ namespace ngraph : Sink(arguments) { } - - /// \brief Returns variable connected to this node. - virtual std::shared_ptr get_variable() const { return m_variable; } - /// \brief Sets a new variable to be connected to this node. - /// - /// \param variable New variable to be connected to this node. - virtual void set_variable(const std::shared_ptr& variable) - { - m_variable = variable; - } - - /// \brief Sets the identifier of corresponding variable - /// - /// \param variable_id New identifier of the variable. - virtual void set_variable_id(const std::string& variable_id){}; - - /// \brief Returns the identifier of corresponding variable. - virtual std::string get_variable_id() const = 0; - - protected: - std::shared_ptr m_variable; }; namespace v3 @@ -61,10 +41,6 @@ namespace ngraph void validate_and_infer_types() override; std::string get_variable_id() const override { return m_variable_id; } - void set_variable_id(const std::string& variable_id) override - { - m_variable_id = variable_id; - } std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; @@ -105,6 +81,11 @@ namespace ngraph "Variable is not initialized. Variable_id is unavailable"); return m_variable->get_info().variable_id; } + bool evaluate(const HostTensorVector& outputs, + const HostTensorVector& inputs, + const EvaluationContext& evaluation_context) const override; + bool constant_fold(OutputVector& output_values, + const OutputVector& inputs_values) override; }; } // namespace v6 } // namespace op diff --git a/ngraph/core/include/ngraph/op/read_value.hpp b/ngraph/core/include/ngraph/op/read_value.hpp index b4978d30b8c..4816d0d9e3b 100644 --- a/ngraph/core/include/ngraph/op/read_value.hpp +++ b/ngraph/core/include/ngraph/op/read_value.hpp @@ -6,12 +6,13 @@ #include "ngraph/op/op.hpp" #include "ngraph/op/util/variable.hpp" +#include "ngraph/op/util/variable_extension.hpp" namespace ngraph { namespace op { - class NGRAPH_API ReadValueBase : public Op + class NGRAPH_API ReadValueBase : public Op, public VariableExtension { public: NGRAPH_RTTI_DECLARATION; @@ -23,28 +24,8 @@ namespace ngraph : Op(arguments) { } - - /// \brief Sets the identifier of corresponding variable - /// - /// \param variable_id New identifier of the variable. - virtual void set_variable_id(const std::string& variable_id){}; - - /// \brief Returns the identifier of corresponding variable. - virtual std::string get_variable_id() const = 0; - - /// \brief Returns variable connected to this node. - virtual std::shared_ptr get_variable() const { return m_variable; } - /// \brief Sets a new variable to be connected to this node. - /// - /// \param variable New variable to be connected to this node. - virtual void set_variable(const std::shared_ptr& variable) - { - m_variable = variable; - } - - protected: - std::shared_ptr m_variable; }; + namespace v3 { /// \brief ReadValue operation creates the variable with `variable_id` and returns value @@ -69,10 +50,6 @@ namespace ngraph bool visit_attributes(AttributeVisitor& visitor) override; std::string get_variable_id() const override { return m_variable_id; } - void set_variable_id(const std::string& variable_id) override - { - m_variable_id = variable_id; - } private: std::string m_variable_id; @@ -113,6 +90,13 @@ namespace ngraph "Variable is not initialized. Variable_id is unavailable"); return m_variable->get_info().variable_id; } + + bool evaluate(const HostTensorVector& outputs, + const HostTensorVector& inputs, + const EvaluationContext& evaluation_context) const override; + + bool constant_fold(OutputVector& output_values, + const OutputVector& inputs_values) override; }; } // namespace v6 } // namespace op diff --git a/ngraph/core/include/ngraph/op/util/broadcast_base.hpp b/ngraph/core/include/ngraph/op/util/broadcast_base.hpp index 6cb822c4941..4c5b4f82402 100644 --- a/ngraph/core/include/ngraph/op/util/broadcast_base.hpp +++ b/ngraph/core/include/ngraph/op/util/broadcast_base.hpp @@ -59,9 +59,10 @@ namespace ngraph const std::pair pair_broadcast_axes, const Shape output_shape) const; - bool evaluate(const HostTensorPtr& arg0, - const HostTensorPtr& out, - const AxisSet& broadcast_axes) const; + bool evaluate_broadcast(const HostTensorPtr& arg0, + const HostTensorPtr& out, + const AxisSet& broadcast_axes) const; + bool evaluate_lower(const HostTensorVector& outputs) const override; bool evaluate_upper(const HostTensorVector& outputs) const override; diff --git a/ngraph/core/include/ngraph/op/util/variable.hpp b/ngraph/core/include/ngraph/op/util/variable.hpp index 287949c562c..6d0f48dafd4 100644 --- a/ngraph/core/include/ngraph/op/util/variable.hpp +++ b/ngraph/core/include/ngraph/op/util/variable.hpp @@ -4,10 +4,9 @@ #pragma once +#include #include -#include "ngraph/op/op.hpp" - namespace ngraph { struct VariableInfo @@ -27,12 +26,14 @@ namespace ngraph { } - VariableInfo get_info() { return m_info; } + VariableInfo get_info() const { return m_info; } void update(const VariableInfo& variable_info) { m_info = variable_info; } private: VariableInfo m_info; }; + using VariablePtr = std::shared_ptr; + using VariableVector = std::vector; template <> class NGRAPH_API AttributeAdapter> diff --git a/ngraph/core/include/ngraph/op/util/variable_context.hpp b/ngraph/core/include/ngraph/op/util/variable_context.hpp new file mode 100644 index 00000000000..200e5cb35d3 --- /dev/null +++ b/ngraph/core/include/ngraph/op/util/variable_context.hpp @@ -0,0 +1,100 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include "ngraph/op/util/variable.hpp" +#include "ngraph/op/util/variable_value.hpp" + +namespace ngraph +{ + using VariableValuePtr = std::shared_ptr; + using VariableMap = std::unordered_map; + + /// VariableContext stores and manages a evaluation context for Variables. + class NGRAPH_API VariableContext + { + public: + /// \brief Constructs an uninitialized VariableContext. + VariableContext() = default; + + /// \brief Constructor for VariableContext. + /// \param variable_values The values associated with a particular Variables. + explicit VariableContext(const VariableMap& variable_values) + : m_variable_values(variable_values) + { + } + + /// \brief Sets the reset flags for all stored Variables to true. + void reset_variable_context() const + { + for (const auto& el : m_variable_values) + { + el.second->set_reset(true); + } + } + + /// \brief Sets the new values for Variables. + /// \param variable_values The new values associated with a particular Variable. + void set_variable_values(const VariableMap& variable_values) + { + m_variable_values = variable_values; + } + + /// \brief Changes/sets the values for Variable. + /// \param variable New or stored Variable. + /// \param variable_value The values associated with the variable. + void set_variable_value(const VariablePtr& variable, const VariableValuePtr& variable_value) + { + m_variable_values[variable] = variable_value; + } + + /// \brief Removes context for a particular Variable. + /// \param variable The variable for which the context will be cleared. + void remove_variable_value(const VariablePtr& variable) + { + m_variable_values.erase(variable); + } + + /// \brief Returns the current values for Variables. + const VariableMap& get_variable_values() const { return m_variable_values; } + + /// \brief Returns the value for specified Variable. + VariableValuePtr get_variable_value(const VariablePtr& variable) const + { + auto var_value = m_variable_values.find(variable); + if (var_value != m_variable_values.end()) + { + return (*var_value).second; + } + return VariableValuePtr(); + } + + private: + /// The values associated with a particular Variable. + VariableMap m_variable_values; + }; + + template <> + class NGRAPH_API VariantWrapper : public VariantImpl + { + public: + static constexpr VariantTypeInfo type_info{"Variant::EvaluationContext::VariableContext", + 0}; + + const VariantTypeInfo& get_type_info() const override { return type_info; } + + explicit VariantWrapper(const value_type& value) + : VariantImpl(value) + { + } + + private: + using Variant::init; + using Variant::merge; + }; + +} // namespace ngraph diff --git a/ngraph/core/include/ngraph/op/util/variable_extension.hpp b/ngraph/core/include/ngraph/op/util/variable_extension.hpp new file mode 100644 index 00000000000..5906c74ea3c --- /dev/null +++ b/ngraph/core/include/ngraph/op/util/variable_extension.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +namespace ngraph +{ + class NGRAPH_API VariableExtension + { + public: + VariableExtension() = default; + + /// \brief Returns variable connected to this node. + virtual std::shared_ptr get_variable() const { return m_variable; } + + /// \brief Sets a new variable to be connected to this node. + /// + /// \param variable New variable to be connected to this node. + virtual void set_variable(const std::shared_ptr& variable) + { + m_variable = variable; + } + + /// \brief Sets the identifier to a variable + /// + /// \param variable_id New identifier of the variable. + virtual void set_variable_id(const std::string& variable_id) + { + m_variable->get_info().variable_id = variable_id; + }; + + /// \brief Returns the identifier of corresponding variable. + virtual std::string get_variable_id() const = 0; + + protected: + std::shared_ptr m_variable; + }; +} // namespace ngraph diff --git a/ngraph/core/include/ngraph/op/util/variable_value.hpp b/ngraph/core/include/ngraph/op/util/variable_value.hpp new file mode 100644 index 00000000000..bab1b4139d0 --- /dev/null +++ b/ngraph/core/include/ngraph/op/util/variable_value.hpp @@ -0,0 +1,55 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +namespace ngraph +{ + /// VariableValue stores data and state (reset flag) for a Variable, + /// and provides an interface for changing them. + class NGRAPH_API VariableValue + { + public: + /// \brief Constructs an uninitialized VariableValue. + VariableValue() = default; + + /// \brief Constructor for VariableValue. + /// \param value The data for Variable. + explicit VariableValue(HostTensorPtr value) + : m_value(std::move(value)) + { + } + + /// \brief Constructor for VariableValue. + /// \param value Data for Variable. + /// \param reset The current state of the reset flag. + VariableValue(HostTensorPtr value, bool reset) + : m_reset(reset) + , m_value(std::move(value)) + { + } + + /// \brief Sets the reset flag to a new state. + /// \param reset The new state of the reset flag. + void set_reset(bool reset) { m_reset = reset; } + + /// \brief Returns the current reset flag state. + bool get_reset() const { return m_reset; } + + /// \brief Returns the current stored data. + const HostTensorPtr& get_value() const { return m_value; } + + /// \brief Sets new values for Variable. + /// \param value New data for Variable. + void set_value(const HostTensorPtr& value) { m_value = value; } + + private: + bool m_reset = true; + HostTensorPtr m_value; + }; + using VariableValuePtr = std::shared_ptr; +} // namespace ngraph diff --git a/ngraph/core/include/ngraph/validation_util.hpp b/ngraph/core/include/ngraph/validation_util.hpp index 353763ab29e..d8922f132a9 100644 --- a/ngraph/core/include/ngraph/validation_util.hpp +++ b/ngraph/core/include/ngraph/validation_util.hpp @@ -10,6 +10,7 @@ #include "ngraph/op/constant.hpp" #include "ngraph/op/op.hpp" #include "ngraph/op/util/attr_types.hpp" +#include "ngraph/op/util/variable_context.hpp" namespace ngraph { @@ -241,9 +242,13 @@ namespace ngraph /// function. /// \param output_tensor_map Tensors to use for particular outputs /// \param outputs Root set of values to try to compute - NGRAPH_API void evaluate_nodes(std::map& value_map, - std::map& output_tensor_map, - const OutputVector& outputs); + /// \param evaluation_context Storage of additional settings and attributes that can be used + /// when evaluating the function. This additional information can be shared across nodes. + NGRAPH_API void + evaluate_nodes(std::map& value_map, + std::map& output_tensor_map, + const OutputVector& outputs, + const EvaluationContext& evaluation_context = EvaluationContext()); /// \brief Evaluates lower value estimation of the output tensor. Traverses graph up to deduce /// estimation through it. diff --git a/ngraph/core/src/function.cpp b/ngraph/core/src/function.cpp index 10db441ec58..7576a21c7dd 100644 --- a/ngraph/core/src/function.cpp +++ b/ngraph/core/src/function.cpp @@ -12,6 +12,9 @@ #include "ngraph/graph_util.hpp" #include "ngraph/log.hpp" #include "ngraph/op/util/op_types.hpp" +#include "ngraph/op/util/variable_context.hpp" +#include "ngraph/op/util/variable_extension.hpp" +#include "ngraph/opsets/opset7.hpp" #include "ngraph/validation_util.hpp" using namespace std; @@ -21,6 +24,70 @@ constexpr DiscreteTypeInfo Function::type_info; atomic Function::m_next_instance_id(0); +void check_all_variables_registered(const std::vector>& ordered_ops, + const VariableVector& variables) +{ + OV_ITT_SCOPED_TASK(ngraph::itt::domains::nGraphPass_LT, + "Function::check_all_variables_registered"); + std::stringstream unregistered_variables; + for (auto& node : ordered_ops) + { + const auto& variable_op = dynamic_pointer_cast(node); + if (variable_op && + std::find(variables.begin(), variables.end(), variable_op->get_variable()) == + variables.end()) + unregistered_variables << variable_op->get_variable_id() << std::endl; + } + if (!unregistered_variables.str().empty()) + throw ngraph_error("Function references undeclared variables: " + + unregistered_variables.str()); +} + +void check_all_parameters_registered(const std::vector>& ordered_ops, + const ParameterVector& parameters) +{ + OV_ITT_SCOPED_TASK(ngraph::itt::domains::nGraph, "Function::check_all_parameters_registered"); + + std::stringstream unregistered_parameters; + for (auto& node : ordered_ops) + { + if (op::is_parameter(node) && + std::find(parameters.begin(), parameters.end(), node) == parameters.end()) + unregistered_parameters << node << std::endl; + } + if (!unregistered_parameters.str().empty()) + throw ngraph_error("Function references undeclared parameters: " + + unregistered_parameters.str()); +} + +VariableVector auto_detect_variables(const std::vector>& ordered_ops) +{ + OV_ITT_SCOPED_TASK(ngraph::itt::domains::nGraph, "Function::auto_detect_variables"); + unordered_set variables; + for (const auto& op : ordered_ops) + { + if (const auto& variable_op = dynamic_pointer_cast(op)) + { + variables.insert(variable_op->get_variable()); + } + } + return VariableVector(variables.begin(), variables.end()); +} + +ParameterVector auto_detect_parameters(const std::vector>& ordered_ops) +{ + OV_ITT_SCOPED_TASK(ngraph::itt::domains::nGraph, "Function::auto_detect_parameters"); + ParameterVector parameter_vector; + for (const auto& op : ordered_ops) + { + if (const auto& param = dynamic_pointer_cast(op)) + { + parameter_vector.push_back(param); + } + } + return parameter_vector; +} + Function::Function(const ResultVector& results, const ParameterVector& parameters, const std::string& name) @@ -30,7 +97,7 @@ Function::Function(const ResultVector& results, , m_results(results) , m_parameters(parameters) { - check_all_parameters_registered(); + prerequirements(true, false); } Function::Function(const OutputVector& results, @@ -42,7 +109,7 @@ Function::Function(const OutputVector& results, , m_results(as_result_vector(results)) , m_parameters(parameters) { - check_all_parameters_registered(); + prerequirements(true, false); } Function::Function(const NodeVector& results, @@ -54,7 +121,7 @@ Function::Function(const NodeVector& results, , m_results(as_result_vector(as_output_vector(results))) , m_parameters(parameters) { - check_all_parameters_registered(); + prerequirements(true, false); } Function::Function(const std::shared_ptr& result, @@ -75,7 +142,7 @@ Function::Function(const ResultVector& results, , m_sinks(sinks) , m_parameters(parameters) { - check_all_parameters_registered(); + prerequirements(true, false); } Function::Function(const OutputVector& results, @@ -86,20 +153,76 @@ Function::Function(const OutputVector& results, { } -void Function::check_all_parameters_registered() const +Function::Function(const ResultVector& results, + const SinkVector& sinks, + const ParameterVector& parameters, + const VariableVector& variables, + const std::string& name) + : m_name(name) + , m_unique_name("Function_" + to_string(m_next_instance_id.fetch_add(1))) + , m_topological_sorter(topological_sort>>) + , m_results(results) + , m_sinks(sinks) + , m_parameters(parameters) + , m_variables(variables) { - OV_ITT_SCOPED_TASK(ngraph::itt::domains::nGraph, "Function::check_all_parameters_registered"); + prerequirements(false, false); +} - std::stringstream unregistered_parameters; - for (auto& node : get_ordered_ops()) - { - if (op::is_parameter(node) && - std::find(m_parameters.begin(), m_parameters.end(), node) == m_parameters.end()) - unregistered_parameters << node << std::endl; - } - if (!unregistered_parameters.str().empty()) - throw ngraph_error("Function references undeclared parameters: " + - unregistered_parameters.str()); +Function::Function(const OutputVector& results, + const SinkVector& sinks, + const ParameterVector& parameters, + const VariableVector& variables, + const std::string& name) + : Function(as_result_vector(results), sinks, parameters, variables, name) +{ +} + +Function::Function(const OutputVector& results, + const ParameterVector& parameters, + const VariableVector& variables, + const std::string& name) + : Function(as_result_vector(results), {}, parameters, variables, name) +{ +} + +Function::Function(const ResultVector& results, + const ParameterVector& parameters, + const VariableVector& variables, + const std::string& name) + : Function(results, {}, parameters, variables, name) +{ +} + +Function::Function(const OutputVector& results, const SinkVector& sinks, const string& name) + : m_name(name) + , m_unique_name("Function_" + to_string(m_next_instance_id.fetch_add(1))) + , m_topological_sorter(topological_sort>>) + , m_results(as_result_vector(results)) + , m_sinks(sinks) +{ + prerequirements(true, true); +} + +Function::Function(const OutputVector& results, const string& name) + : Function(results, SinkVector{}, name) +{ +} + +void Function::prerequirements(bool detect_variables, bool detect_parameters) +{ + OV_ITT_SCOPED_TASK(ngraph::itt::domains::nGraph, "Function::prerequirements"); + + const auto& ordered_ops = get_ordered_ops(); + if (detect_parameters) + m_parameters = auto_detect_parameters(ordered_ops); + else + check_all_parameters_registered(ordered_ops, m_parameters); + + if (detect_variables) + m_variables = auto_detect_variables(ordered_ops); + else + check_all_variables_registered(ordered_ops, m_variables); } void Function::validate_nodes_and_infer_types() const @@ -113,12 +236,20 @@ void Function::validate_nodes_and_infer_types() const }; std::map pair_checker; std::stringstream unregistered_parameters; + std::stringstream unregistered_variables; for (auto& node : get_ordered_ops()) { node->revalidate_and_infer_types(); if (op::is_parameter(node) && std::find(m_parameters.begin(), m_parameters.end(), node) == m_parameters.end()) unregistered_parameters << node << std::endl; + + const auto& variable_op = dynamic_pointer_cast(node); + if (variable_op && + std::find(m_variables.begin(), m_variables.end(), variable_op->get_variable()) == + m_variables.end()) + unregistered_variables << variable_op->get_variable_id() << std::endl; + if (const auto& assign = std::dynamic_pointer_cast(node)) { pair_checker[assign->get_variable().get()].cnt_assign++; @@ -132,6 +263,9 @@ void Function::validate_nodes_and_infer_types() const throw ngraph_error("Function references undeclared parameters: " + unregistered_parameters.str()); + if (!unregistered_variables.str().empty()) + throw ngraph_error("Function references undeclared Variables: " + + unregistered_variables.str()); bool only_pairs = std::all_of( pair_checker.begin(), pair_checker.end(), [](const std::pair& val) { return val.second.cnt_assign == 1 && val.second.cnt_read_val == 1; @@ -180,7 +314,7 @@ void Function::map_unordered_ops(std::function f) const { remaining_ops.push(param.get()); } - while (remaining_ops.size() > 0) + while (!remaining_ops.empty()) { Node* op = remaining_ops.top(); remaining_ops.pop(); @@ -375,8 +509,12 @@ int64_t Function::get_result_index(const Output& value) const } bool Function::evaluate(const HostTensorVector& output_tensors, - const HostTensorVector& input_tensors) const + const HostTensorVector& input_tensors, + EvaluationContext evaluation_context) const { + if (evaluation_context.find("VariableContext") == evaluation_context.end()) + evaluation_context["VariableContext"] = + std::make_shared>(VariableContext()); std::map value_map; for (size_t i = 0; i < m_parameters.size(); ++i) { @@ -390,7 +528,7 @@ bool Function::evaluate(const HostTensorVector& output_tensors, output_tensor_map[result] = output_tensors.at(i); outputs.push_back(result); } - evaluate_nodes(value_map, output_tensor_map, outputs); + evaluate_nodes(value_map, output_tensor_map, outputs, evaluation_context); return true; } @@ -404,6 +542,17 @@ bool Function::visit_attributes(AttributeVisitor& visitor) void Function::add_sinks(const SinkVector& sinks) { m_sinks.insert(m_sinks.end(), sinks.begin(), sinks.end()); + for (const auto& sink : sinks) + { + if (const auto& variable_op = dynamic_pointer_cast(sink)) + { + if (find(m_variables.begin(), m_variables.end(), variable_op->get_variable()) == + m_variables.end()) + { + m_variables.push_back(variable_op->get_variable()); + } + } + } } void Function::remove_sink(const std::shared_ptr& sink) @@ -453,4 +602,29 @@ void Function::remove_parameter(const std::shared_ptr& param) m_parameters.end()); } +void Function::add_variables(const VariableVector& variables) +{ + m_variables.insert(m_variables.end(), variables.begin(), variables.end()); +} + +void Function::remove_variable(const VariablePtr& variable) +{ + m_variables.erase(std::remove_if(m_variables.begin(), + m_variables.end(), + [&variable](VariablePtr& v) { return v == variable; }), + m_variables.end()); +} + +VariablePtr Function::get_variable_by_id(const string& variable_id) const +{ + auto variable = std::find_if( + m_variables.begin(), m_variables.end(), [&variable_id](const VariablePtr& cur) { + return cur->get_info().variable_id == variable_id; + }); + if (variable != m_variables.end()) + return *variable; + else + return VariablePtr(); +} + constexpr DiscreteTypeInfo AttributeAdapter>::type_info; diff --git a/ngraph/core/src/node.cpp b/ngraph/core/src/node.cpp index 3743e221f1a..d0df4bd2b4f 100644 --- a/ngraph/core/src/node.cpp +++ b/ngraph/core/src/node.cpp @@ -949,6 +949,13 @@ bool Node::evaluate(const HostTensorVector& output_values, return false; } +bool Node::evaluate(const HostTensorVector& output_values, + const HostTensorVector& input_values, + const EvaluationContext& evaluationContext) const +{ + return evaluate(output_values, input_values); +} + bool Node::evaluate_lower(const HostTensorVector& output_values) const { const auto& inputs = input_values(); diff --git a/ngraph/core/src/op/assign.cpp b/ngraph/core/src/op/assign.cpp index 4159cbe6463..1c1cb9883b0 100644 --- a/ngraph/core/src/op/assign.cpp +++ b/ngraph/core/src/op/assign.cpp @@ -6,6 +6,7 @@ #include "itt.hpp" #include "ngraph/op/read_value.hpp" #include "ngraph/op/util/variable.hpp" +#include "ngraph/op/util/variable_context.hpp" #include "ngraph/ops.hpp" using namespace std; @@ -111,4 +112,46 @@ bool op::v6::Assign::visit_attributes(AttributeVisitor& visitor) NGRAPH_OP_SCOPE(v6_Assign_visit_attributes); visitor.on_attribute("variable_id", m_variable); return true; +} + +bool op::v6::Assign::evaluate(const HostTensorVector& outputs, + const HostTensorVector& inputs, + const EvaluationContext& evaluation_context) const +{ + NGRAPH_OP_SCOPE(v6_Assign_evaluate); + const auto& found_context = evaluation_context.find("VariableContext"); + NODE_VALIDATION_CHECK( + this, found_context != evaluation_context.end(), "VariableContext not found."); + + auto variable_context = + std::dynamic_pointer_cast>(found_context->second); + NODE_VALIDATION_CHECK( + this, variable_context != nullptr, "Cannot cast found Context to VariableContext."); + const auto& variable_values = variable_context->get().get_variable_values(); + + // automatically allocate memory if not provided by user + if (variable_values.find(m_variable) == variable_values.end()) + { + auto host_tensor = std::make_shared(m_variable->get_info().data_type, + m_variable->get_info().data_shape); + variable_context->get().set_variable_value(m_variable, + make_shared(host_tensor)); + } + + const auto var_value = variable_values.find(m_variable)->second; + var_value->set_reset(false); + const auto& buffer = var_value->get_value(); + buffer->set_unary(inputs[0]); + outputs[0]->set_unary(inputs[0]); + + void* input = inputs[0]->get_data_ptr(); + outputs[0]->write(input, outputs[0]->get_size_in_bytes()); + buffer->write(input, buffer->get_size_in_bytes()); + + return true; +} + +bool op::v6::Assign::constant_fold(OutputVector& output_values, const OutputVector& inputs_values) +{ + return false; } \ No newline at end of file diff --git a/ngraph/core/src/op/read_value.cpp b/ngraph/core/src/op/read_value.cpp index 4136d390b67..1e1d51c292c 100644 --- a/ngraph/core/src/op/read_value.cpp +++ b/ngraph/core/src/op/read_value.cpp @@ -4,6 +4,8 @@ #include "ngraph/op/read_value.hpp" #include "itt.hpp" +#include "ngraph/op/util/variable_context.hpp" +#include "ngraph/ops.hpp" using namespace std; using namespace ngraph; @@ -93,4 +95,40 @@ void op::v6::ReadValue::revalidate_and_infer_types() PartialShape::dynamic(), element::dynamic, m_variable->get_info().variable_id}; m_variable->update(var_info); Node::revalidate_and_infer_types(); +} + +bool op::v6::ReadValue::evaluate(const HostTensorVector& outputs, + const HostTensorVector& inputs, + const EvaluationContext& evaluation_context) const +{ + NGRAPH_OP_SCOPE(v6_ReadValue_evaluate); + const auto& found_context = evaluation_context.find("VariableContext"); + NODE_VALIDATION_CHECK( + this, found_context != evaluation_context.end(), "VariableContext not found."); + + auto variable_context = + std::dynamic_pointer_cast>(found_context->second); + NODE_VALIDATION_CHECK( + this, variable_context != nullptr, "Cannot cast found Context to VariableContext."); + const auto& variable_values = variable_context->get().get_variable_values(); + const auto& var_value = variable_values.find(m_variable); + + bool use_context = var_value != variable_values.end() && !var_value->second->get_reset(); + + // initial value (inputs[0]) is not supported, use zeros + auto zero_const = + make_shared(inputs[0]->get_element_type(), inputs[0]->get_shape(), 0); + auto zero_tensor = make_shared(zero_const); + const auto& input_tensor = use_context ? var_value->second->get_value() : zero_tensor; + outputs[0]->set_unary(input_tensor); + + void* input = input_tensor->get_data_ptr(); + outputs[0]->write(input, outputs[0]->get_size_in_bytes()); + return true; +} + +bool op::v6::ReadValue::constant_fold(OutputVector& output_values, + const OutputVector& inputs_values) +{ + return false; } \ No newline at end of file diff --git a/ngraph/core/src/op/result.cpp b/ngraph/core/src/op/result.cpp index c8b48ccbef3..d825f731f1a 100644 --- a/ngraph/core/src/op/result.cpp +++ b/ngraph/core/src/op/result.cpp @@ -54,6 +54,7 @@ bool op::Result::evaluate(const HostTensorVector& outputs, const HostTensorVecto void* output = outputs[0]->get_data_ptr(); void* input = inputs[0]->get_data_ptr(); memcpy(output, input, outputs[0]->get_size_in_bytes()); + return true; } diff --git a/ngraph/core/src/op/util/broadcast_base.cpp b/ngraph/core/src/op/util/broadcast_base.cpp index 3264a6a29ce..c6ecdd69f8f 100644 --- a/ngraph/core/src/op/util/broadcast_base.cpp +++ b/ngraph/core/src/op/util/broadcast_base.cpp @@ -365,9 +365,9 @@ std::pair op::util::BroadcastBase::get_broadcast_axes() const return std::make_pair(axes_known, broadcast_axes); } -bool op::util::BroadcastBase::evaluate(const HostTensorPtr& arg0, - const HostTensorPtr& out, - const AxisSet& broadcast_axes) const +bool op::util::BroadcastBase::evaluate_broadcast(const HostTensorPtr& arg0, + const HostTensorPtr& out, + const AxisSet& broadcast_axes) const { NGRAPH_OP_SCOPE(util_BroadcastBase_evaluate_axes); auto arg0_shape = arg0->get_shape(); @@ -491,7 +491,7 @@ bool op::util::BroadcastBase::evaluate_broadcast(const HostTensorPtr& arg0, out->set_shape(output_shape); out->set_element_type(arg0->get_element_type()); - return evaluate(arg0, out, pair_broadcast_axes.second); + return evaluate_broadcast(arg0, out, pair_broadcast_axes.second); } Shape op::util::BroadcastBase::get_target_shape(const HostTensorPtr& input1) const diff --git a/ngraph/core/src/op/util/evaluation_context.cpp b/ngraph/core/src/op/util/evaluation_context.cpp new file mode 100644 index 00000000000..4b13d745a46 --- /dev/null +++ b/ngraph/core/src/op/util/evaluation_context.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "ngraph/op/util/variable_context.hpp" + +constexpr ngraph::VariantTypeInfo ngraph::VariantWrapper::type_info; diff --git a/ngraph/core/src/validation_util.cpp b/ngraph/core/src/validation_util.cpp index d41a4334f50..1671892879a 100644 --- a/ngraph/core/src/validation_util.cpp +++ b/ngraph/core/src/validation_util.cpp @@ -1262,14 +1262,15 @@ pair ngraph::maximum_value(const Output& value) void ngraph::evaluate_nodes(std::map& value_map, std::map& output_tensor_map, - const OutputVector& outputs) + const OutputVector& outputs, + const EvaluationContext& evaluation_context) { Evaluator evaluator({}, value_map); evaluator.set_univeral_handler( - [&output_tensor_map](Node* node, - const HostTensorVector& input_tensors) -> HostTensorVector { + [&output_tensor_map, &evaluation_context]( + Node* node, const HostTensorVector& input_tensors) -> HostTensorVector { HostTensorVector output_tensors; - for (auto v : node->outputs()) + for (const auto& v : node->outputs()) { auto it = output_tensor_map.find(v); if (it == output_tensor_map.end()) @@ -1282,7 +1283,7 @@ void ngraph::evaluate_nodes(std::map& value_map, output_tensors.push_back(it->second); } } - if (node->evaluate(output_tensors, input_tensors)) + if (node->evaluate(output_tensors, input_tensors, evaluation_context)) { return output_tensors; } @@ -1291,7 +1292,7 @@ void ngraph::evaluate_nodes(std::map& value_map, NGRAPH_CHECK(false, "Evaluation failed on ", node); } }); - for (auto value : outputs) + for (const auto& value : outputs) { evaluator.evaluate(value); } diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 739bc1b498f..7164ebbea7c 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC op_eval/hswish.cpp op_eval/interpolate.cpp op_eval/matmul.cpp + op_eval/memory.cpp op_eval/mish.cpp op_eval/non_zero.cpp op_eval/reduce_l1.cpp diff --git a/ngraph/test/build_graph.cpp b/ngraph/test/build_graph.cpp index 88d9947170e..9f4aa35cf78 100644 --- a/ngraph/test/build_graph.cpp +++ b/ngraph/test/build_graph.cpp @@ -8,6 +8,7 @@ #include "ngraph/file_util.hpp" #include "ngraph/ngraph.hpp" #include "ngraph/opsets/opset5.hpp" +#include "ngraph/opsets/opset7.hpp" #include "util/test_tools.hpp" #include @@ -443,4 +444,119 @@ TEST(build_graph, build_graph_with_remove_parameter_indexing) EXPECT_EQ(nodes.size(), 9); f->validate_nodes_and_infer_types(); +} + +TEST(build_graph, build_graph_parameters_autodetection) +{ + // Function with 4 parameters + using namespace opset7; + auto arg0 = make_shared(element::f32, Shape{7, 3}); + auto arg1 = make_shared(element::f32, Shape{3}); + auto arg2 = make_shared(element::f32, Shape{32, 7}); + auto arg3 = make_shared(element::f32, Shape{32, 7}); + auto broadcast_1 = builder::opset1::make_broadcast(arg3, Shape{10, 32, 7}, AxisSet{0}); + auto b1 = builder::opset1::make_broadcast(arg3, Shape{10, 32, 7}, AxisSet{0}); + auto dot = make_shared(arg2, arg0); + + auto f = make_shared(OutputVector{dot}); + EXPECT_EQ(f->get_parameters().size(), 2); +} + +TEST(build_graph, build_graph_parameters_variables_autodetection) +{ + using namespace opset7; + auto arg = make_shared(element::f32, Shape{2, 4}); + auto arg2 = make_shared(element::f32, Shape{2, 2}); + auto init_const = Constant::create(element::f32, Shape{2, 2}, {0, 0, 0, 0}); + + auto variable = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "v0"}); + auto read = make_shared(init_const, variable); + auto assign = make_shared(read, variable); + assign->add_control_dependency(read); + + std::vector> args = {arg2, arg}; + auto pattern = make_shared(args, 1); + auto res = make_shared(pattern); + const auto axis = Constant::create(element::i64, Shape{}, {1}); + auto crop = make_shared(pattern, axis, 3); + auto res2 = make_shared(crop, "v0"); + + auto f = make_shared(OutputVector{res, res2}, SinkVector{assign}); + + NodeVector nodes = f->get_ops(); + EXPECT_EQ(nodes.size(), 10); + ParameterVector params = f->get_parameters(); + EXPECT_EQ(params.size(), 2); + VariableVector variables = f->get_variables(); + EXPECT_EQ(variables.size(), 1); +} + +TEST(build_graph, build_graph_variables_ctors) +{ + using namespace opset7; + auto arg = make_shared(element::f32, Shape{2, 4}); + auto arg2 = make_shared(element::f32, Shape{2, 2}); + auto init_const = Constant::create(element::f32, Shape{2, 2}, {0, 0, 0, 0}); + + auto variable = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "v0"}); + auto read = make_shared(init_const, variable); + auto assign = make_shared(read, variable); + assign->add_control_dependency(read); + + std::vector> args = {arg2, arg}; + auto pattern = make_shared(args, 1); + auto res = make_shared(pattern); + const auto axis = Constant::create(element::i64, Shape{}, {1}); + auto crop = make_shared(pattern, axis, 3); + auto res2 = make_shared(crop, "v0"); + + { + auto f = make_shared(OutputVector{res, res2}, SinkVector{assign}, + ParameterVector{arg, arg2}, VariableVector{variable}); + + NodeVector nodes = f->get_ops(); + EXPECT_EQ(nodes.size(), 10); + ParameterVector params = f->get_parameters(); + EXPECT_EQ(params.size(), 2); + VariableVector variables = f->get_variables(); + EXPECT_EQ(variables.size(), 1); + } + + // autodetect variables + { + auto f = make_shared(OutputVector{res, res2}, SinkVector{assign}, + ParameterVector{arg, arg2}); + NodeVector nodes = f->get_ops(); + EXPECT_EQ(nodes.size(), 10); + ParameterVector params = f->get_parameters(); + EXPECT_EQ(params.size(), 2); + VariableVector variables = f->get_variables(); + EXPECT_EQ(variables.size(), 1); + } +} + +TEST(build_graph, build_graph_unregistred_variables) +{ + using namespace opset7; + auto arg = make_shared(element::f32, Shape{2, 4}); + auto arg2 = make_shared(element::f32, Shape{2, 2}); + auto init_const = Constant::create(element::f32, Shape{2, 2}, {0, 0, 0, 0}); + + auto variable = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "v0"}); + auto variable_2 = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "v1"}); + auto read = make_shared(init_const, variable); + auto read_2 = make_shared(init_const, variable_2); + auto assign = make_shared(read, variable); + auto assign_2 = make_shared(read_2, variable_2); + assign->add_control_dependency(read); + + std::vector> args = {arg2, arg}; + auto pattern = make_shared(args, 1); + auto res = make_shared(pattern); + const auto axis = Constant::create(element::i64, Shape{}, {1}); + auto crop = make_shared(pattern, axis, 3); + auto res2 = make_shared(crop, "v0"); + + EXPECT_ANY_THROW(make_shared(OutputVector{res, res2}, SinkVector{assign, assign_2}, + ParameterVector{arg, arg2}, VariableVector{variable})); } \ No newline at end of file diff --git a/ngraph/test/op_eval/memory.cpp b/ngraph/test/op_eval/memory.cpp new file mode 100644 index 00000000000..dd9b6eb648f --- /dev/null +++ b/ngraph/test/op_eval/memory.cpp @@ -0,0 +1,316 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "gtest/gtest.h" + +#include "ngraph/opsets/opset7.hpp" +#include "ngraph/op/util/variable.hpp" +#include "ngraph/variant.hpp" +#include "ngraph/validation_util.hpp" +#include "ngraph/op/util/variable_context.hpp" + +#include "util/all_close_f.hpp" +#include "util/test_tools.hpp" + +using namespace std; +using namespace ngraph; +using namespace ngraph::opset7; + +constexpr ngraph::VariantTypeInfo ngraph::VariantWrapper::type_info; + +shared_ptr AssignReadGraph() { + auto p = make_shared(element::f32, Shape{3}); + auto variable = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "var_1"}); + auto read_value = make_shared(p, variable); + auto assign = make_shared(read_value, variable); + return make_shared(OutputVector{assign}, ParameterVector{p}, VariableVector{variable}); +} + +shared_ptr AssignReadAddGraph() { + auto p = make_shared(element::f32, Shape{3}); + auto c = std::make_shared(element::f32, Shape{3}, std::vector({0, 0, 0})); + auto variable = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "var_1"}); + auto read_value = make_shared(c, variable); + auto add = make_shared(p, read_value); + auto assign = make_shared(add, variable); + return make_shared(OutputVector{assign}, ParameterVector{p}, VariableVector{variable}); +} + +shared_ptr AssignReadMultiVariableGraph() { + auto c = std::make_shared(element::f32, Shape{3}, std::vector({0, 0, 0})); + + auto variable = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "var_1"}); + auto variable_2 = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "var_2"}); + + auto read_value = make_shared(c, variable); + auto read_value_2 = make_shared(c, variable_2); + + auto add = make_shared(read_value_2, read_value); + + auto assign = make_shared(add, variable); + auto assign_2 = make_shared(read_value_2, variable_2); + + return make_shared(OutputVector{assign}, ParameterVector{}, VariableVector{variable, variable_2}); +} + +TEST(op_eval, assign_readvalue_without_evaluation_context) +{ + auto fun = AssignReadGraph(); + auto result = make_shared(); + + const int COUNT_RUNS = 10; + std::vector inputs{-5, 0, 5}; + std::vector expected_result{0, 0, 0}; + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE(fun->evaluate({result}, {make_host_tensor(Shape{3}, inputs)})); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } +} + +TEST(op_eval, assign_readvalue_evaluation_context) +{ + auto fun = AssignReadGraph(); + auto result = make_shared(); + const auto& variables = fun->get_variables(); + EXPECT_EQ(variables.size(), 1); + + std::vector inputs{-5, 0, 5}; + std::vector expected_result{0, 0, 0}; + + EvaluationContext eval_context; + HostTensorPtr h_tensor = make_host_tensor(Shape{3}, inputs); + VariableContext variable_context; + variable_context.set_variable_value(variables[0], std::make_shared(h_tensor)); + eval_context["VariableContext"] = std::make_shared>(variable_context); + + const int COUNT_RUNS = 10; + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE(fun->evaluate({result}, {make_host_tensor(Shape{3}, inputs)}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } +} + +TEST(op_eval, assign_readvalue_add) +{ + auto fun = AssignReadAddGraph(); + const auto& variables = fun->get_variables(); + EXPECT_EQ(variables.size(), 1); + + std::vector inputs{-5, 0, 5}; + + // creating context + EvaluationContext eval_context; + auto variable_context = std::make_shared>(VariableContext()); + auto variable_value = make_shared(make_host_tensor(Shape{3}, inputs)); + variable_context->get().set_variable_value(variables[0], variable_value); + eval_context["VariableContext"] = variable_context; + + auto result = make_shared(); + const int COUNT_RUNS = 10; + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE( + fun->evaluate({result}, {make_host_tensor(Shape{3}, inputs)}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + auto result_data = read_vector(result); + + auto cnt = static_cast(i+1); + std::vector expected_result{inputs[0] * cnt, inputs[1] * cnt, inputs[2] * cnt}; + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } +} + +TEST(op_eval, assign_readvalue_reset_before_evaluate) +{ + auto fun = AssignReadAddGraph(); + const auto& variables = fun->get_variables(); + EXPECT_EQ(variables.size(), 1); + + std::vector inputs{-5, 0, 5}; + + // creating context + EvaluationContext eval_context; + auto variable_context = std::make_shared>(VariableContext()); + auto variable_value = make_shared(make_host_tensor(Shape{3}, inputs)); + variable_value->set_reset(false); + variable_context->get().set_variable_value(variables[0], variable_value); + eval_context["VariableContext"] = variable_context; + + auto result = make_shared(); + const int COUNT_RUNS = 10; + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE( + fun->evaluate({result}, {make_host_tensor(Shape{3}, inputs)}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + auto result_data = read_vector(result); + + auto cnt = static_cast(i+2); + std::vector expected_result{inputs[0] * cnt, inputs[1] * cnt, inputs[2] * cnt}; + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } +} + +TEST(op_eval, assign_readvalue_add_reset) +{ + auto fun = AssignReadAddGraph(); + std::vector inputs{-5, 0, 5}; + const auto& variables = fun->get_variables(); + EXPECT_EQ(variables.size(), 1); + + // creating a Context + EvaluationContext eval_context; + auto variable_context = std::make_shared>(VariableContext()); + auto variable_value = make_shared(make_host_tensor(Shape{3}, inputs)); + variable_context->get().set_variable_value(variables[0], variable_value); + eval_context["VariableContext"] = variable_context; + + auto result = make_shared(); + const int COUNT_RUNS = 10; + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE( + fun->evaluate({result}, {make_host_tensor(Shape{3}, inputs)}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + auto result_data = read_vector(result); + + auto cnt = static_cast(i+1); + std::vector expected_result{inputs[0] * cnt, inputs[1] * cnt, inputs[2] * cnt}; + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } + + const auto& found_context = eval_context.find("VariableContext"); + EXPECT_NE(found_context, eval_context.end()); + auto var_context = std::dynamic_pointer_cast>(found_context->second); + EXPECT_NE(var_context, nullptr); + variable_context->get().reset_variable_context(); + + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE( + fun->evaluate({result}, {make_host_tensor(Shape{3}, inputs)}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + auto result_data = read_vector(result); + + auto cnt = static_cast(i+1); + std::vector expected_result{inputs[0] * cnt, inputs[1] * cnt, inputs[2] * cnt}; + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } +} + +TEST(op_eval, assign_readvalue_add_modify) +{ + auto fun = AssignReadAddGraph(); + std::vector inputs{-5, 0, 5}; + const auto& variables = fun->get_variables(); + EXPECT_EQ(variables.size(), 1); + + // creating context + EvaluationContext eval_context; + auto variable_context = std::make_shared>(VariableContext()); + auto variable_value = make_shared(make_host_tensor(Shape{3}, inputs)); + variable_context->get().set_variable_value(variables[0], variable_value); + eval_context["VariableContext"] = variable_context; + + auto result = make_shared(); + const int COUNT_RUNS = 10; + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE( + fun->evaluate({result}, {make_host_tensor(Shape{3}, inputs)}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + + auto cnt = static_cast(i+1); + std::vector expected_result{inputs[0] * cnt, inputs[1] * cnt, inputs[2] * cnt}; + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } + + const auto& found_context = eval_context.find("VariableContext"); + EXPECT_NE(found_context, eval_context.end()); + auto var_context = std::dynamic_pointer_cast>(found_context->second); + EXPECT_NE(var_context, nullptr); + const auto& var_value = variable_context->get().get_variable_value(variables[0]); + EXPECT_NE(var_value, nullptr); + var_value->set_value(make_host_tensor(Shape{3}, {1, 2, 3})); + + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE( + fun->evaluate({result}, {make_host_tensor(Shape{3}, inputs)}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + + auto cnt = static_cast(i+1); + std::vector expected_result{1 + inputs[0] * cnt, 2 + inputs[1] * cnt, 3 + inputs[2] * cnt}; + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } +} + +TEST(op_eval, assign_readvalue_add_modify_multi_variables) +{ + auto fun = AssignReadMultiVariableGraph(); + std::vector inputs_1{2, 2, 2}; + std::vector inputs_2{1, 3, 5}; + auto var_1 = fun->get_variable_by_id("var_1"); + auto var_2 = fun->get_variable_by_id("var_2"); + EXPECT_NE(var_1, nullptr); + EXPECT_NE(var_2, nullptr); + + // creating context + EvaluationContext eval_context; + auto variable_context = std::make_shared>(VariableContext()); + auto variable_value_1 = make_shared(make_host_tensor(Shape{3}, inputs_1)); + auto variable_value_2 = make_shared(make_host_tensor(Shape{3}, inputs_2)); + variable_value_1->set_reset(false); + variable_value_2->set_reset(false); + variable_context->get().set_variable_value(var_1, variable_value_1); + variable_context->get().set_variable_value(var_2, variable_value_2); + eval_context["VariableContext"] = variable_context; + + auto result = make_shared(); + const int COUNT_RUNS = 10; + + std::vector expected_result = inputs_1; + for (size_t i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE(fun->evaluate({result}, {}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + + for (size_t j = 0; j < expected_result.size(); ++j) { + expected_result[j] += inputs_2[j]; + } + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } + + const auto& found_context = eval_context.find("VariableContext"); + EXPECT_NE(found_context, eval_context.end()); + auto var_context = std::dynamic_pointer_cast>(found_context->second); + EXPECT_NE(var_context, nullptr); + + auto var_value = variable_context->get().get_variable_value(var_1); + EXPECT_NE(var_value, nullptr); + var_value->set_value(make_host_tensor(Shape{3}, {1, 2, 3})); + + auto var_value_2 = variable_context->get().get_variable_value(var_2); + EXPECT_NE(var_value_2, nullptr); + var_value_2->set_reset(true); + + expected_result = {1, 2, 3}; + for (int i = 0; i < COUNT_RUNS; ++i) { + ASSERT_TRUE( + fun->evaluate({result}, {}, eval_context)); + EXPECT_EQ(result->get_element_type(), element::f32); + EXPECT_EQ(result->get_shape(), Shape{3}); + + ASSERT_TRUE(test::all_close_f(read_vector(result), expected_result)); + } +} From 02b31b2cc71509bb1fcc967b88dd5760740a2a27 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 17 May 2021 21:02:56 +0300 Subject: [PATCH 95/99] Follow-up for PR 5638 (#5659) --- cmake/developer_package/download/dependency_solver.cmake | 6 +++--- inference-engine/cmake/ie_parallel.cmake | 6 +++--- inference-engine/src/vpu/graph_transformer/CMakeLists.txt | 6 +++--- .../tests/functional/inference_engine/CMakeLists.txt | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmake/developer_package/download/dependency_solver.cmake b/cmake/developer_package/download/dependency_solver.cmake index 9038f610035..2f2ab192d3e 100644 --- a/cmake/developer_package/download/dependency_solver.cmake +++ b/cmake/developer_package/download/dependency_solver.cmake @@ -176,9 +176,9 @@ function(reset_deps_cache) foreach(var_name IN LISTS ARGN) unset(${var_name} CACHE) endforeach() - # foreach(var_name IN LISTS ARGN) - # unset(ENV{${var_name}}) - # endforeach() + foreach(var_name IN LISTS ARGN) + unset(ENV{${var_name}}) + endforeach() endif() endfunction() diff --git a/inference-engine/cmake/ie_parallel.cmake b/inference-engine/cmake/ie_parallel.cmake index 958ea9b23a7..a4960ce3430 100644 --- a/inference-engine/cmake/ie_parallel.cmake +++ b/inference-engine/cmake/ie_parallel.cmake @@ -25,9 +25,9 @@ function(set_ie_threading_interface_for TARGET_NAME) else() find_dependency(TBB COMPONENTS tbb tbbmalloc) endif() - set("TBB_FOUND" ${TBB_FOUND} PARENT_SCOPE) - set("TBB_IMPORTED_TARGETS" ${TBB_IMPORTED_TARGETS} PARENT_SCOPE) - set("TBB_VERSION" ${TBB_VERSION} PARENT_SCOPE) + set(TBB_FOUND ${TBB_FOUND} PARENT_SCOPE) + set(TBB_IMPORTED_TARGETS ${TBB_IMPORTED_TARGETS} PARENT_SCOPE) + set(TBB_VERSION ${TBB_VERSION} PARENT_SCOPE) if (NOT TBB_FOUND) ext_message(WARNING "TBB was not found by the configured TBB_DIR/TBBROOT path.\ SEQ method will be used.") diff --git a/inference-engine/src/vpu/graph_transformer/CMakeLists.txt b/inference-engine/src/vpu/graph_transformer/CMakeLists.txt index 872f0bef2e3..bc73ab5b155 100644 --- a/inference-engine/src/vpu/graph_transformer/CMakeLists.txt +++ b/inference-engine/src/vpu/graph_transformer/CMakeLists.txt @@ -12,9 +12,9 @@ function(add_graph_transformer_target TARGET_NAME STATIC_IE) # To avoid further TBB find_package action in next call of this function. Some version of TBB # has an issue with cmake config which lead to fail in case of multiple call of find_package # from one cmake script file. - set("TBB_FOUND" ${TBB_FOUND} PARENT_SCOPE) - set("TBB_IMPORTED_TARGETS" ${TBB_IMPORTED_TARGETS} PARENT_SCOPE) - set("TBB_VERSION" ${TBB_VERSION} PARENT_SCOPE) + set(TBB_FOUND ${TBB_FOUND} PARENT_SCOPE) + set(TBB_IMPORTED_TARGETS ${TBB_IMPORTED_TARGETS} PARENT_SCOPE) + set(TBB_VERSION ${TBB_VERSION} PARENT_SCOPE) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # TODO: enable some day and fix all warnings diff --git a/inference-engine/tests/functional/inference_engine/CMakeLists.txt b/inference-engine/tests/functional/inference_engine/CMakeLists.txt index e6eefc809af..2c4d97b87f2 100644 --- a/inference-engine/tests/functional/inference_engine/CMakeLists.txt +++ b/inference-engine/tests/functional/inference_engine/CMakeLists.txt @@ -169,9 +169,9 @@ function(ie_headers_compilation_with_custom_flags) # To avoid further TBB find_package action in next call of this function. Some version of TBB # has an issue with cmake config which lead to fail in case of multiple call of find_package # from one cmake script file. - set("TBB_FOUND" ${TBB_FOUND} PARENT_SCOPE) - set("TBB_IMPORTED_TARGETS" ${TBB_IMPORTED_TARGETS} PARENT_SCOPE) - set("TBB_VERSION" ${TBB_VERSION} PARENT_SCOPE) + set(TBB_FOUND ${TBB_FOUND} PARENT_SCOPE) + set(TBB_IMPORTED_TARGETS ${TBB_IMPORTED_TARGETS} PARENT_SCOPE) + set(TBB_VERSION ${TBB_VERSION} PARENT_SCOPE) set_target_properties(${target_name} PROPERTIES CXX_STANDARD ${IE_TEST_CXX_STANDARD} From 71b87255abb2dda1582f2a959992d1b2388de7aa Mon Sep 17 00:00:00 2001 From: Mikhail Treskin Date: Mon, 17 May 2021 22:47:29 +0300 Subject: [PATCH 96/99] Skip Assign and ReadValue from extractor. (#5663) --- .../plugin/conformance/subgraphs_dumper/src/ops_cache.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/ops_cache.cpp b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/ops_cache.cpp index 2981709e5a2..b0105debd18 100644 --- a/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/ops_cache.cpp +++ b/inference-engine/tests/functional/plugin/conformance/subgraphs_dumper/src/ops_cache.cpp @@ -42,7 +42,12 @@ void OPCache::update_ops_cache(const std::shared_ptr &func, co for (const auto &op : func->get_ordered_ops()) { if (ngraph::is_type(op) || ngraph::is_type(op) || - ngraph::is_type(op)) { + ngraph::is_type(op) || + // ReadValue and Assign have to be handled in pair + // Will be handled as part of 48838 + ngraph::is_type(op) || + ngraph::is_type(op) + ) { continue; } update_ops_cache(op, source_model); From 4d6d088c02b7fd597dc7d7f7a705f1d0a340bb03 Mon Sep 17 00:00:00 2001 From: Irina Efode Date: Mon, 17 May 2021 23:08:42 +0300 Subject: [PATCH 97/99] [IE TESTS] Add tag to the report (for identification scope) && add handling of exception in merge_xmls (#5660) --- .../layer_tests_summary/merge_xmls.py | 6 +++++- .../layer_tests_summary/summarize.py | 8 +++++--- .../layer_tests_summary/template/report_template.html | 5 +++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/merge_xmls.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/merge_xmls.py index f874f01ebab..d17c60b6b79 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/merge_xmls.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/merge_xmls.py @@ -28,7 +28,11 @@ def aggregate_test_results(results: ET.SubElement, xml_reports: list): timestamp = None for xml in xml_reports: logger.info(f" Processing: {xml}") - xml_root = ET.parse(xml).getroot() + try: + xml_root = ET.parse(xml).getroot() + except ET.ParseError: + logger.error(f' {xml} is corrupted and skipped') + continue xml_timestamp = xml_root.get("timestamp") if (timestamp is None) or (xml_timestamp < timestamp): timestamp = xml_timestamp diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/summarize.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/summarize.py index 9ba9dea8a98..519cef7d01a 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/summarize.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/summarize.py @@ -22,9 +22,11 @@ def parse_arguments(): report is be kept. """ out_help = "Path where to save html report" + report_tag = "Report tag" parser.add_argument("--xml", help=xml_help, nargs="*", required=True) parser.add_argument("--out", help=out_help, default="") + parser.add_argument("--report_tag", help=report_tag, default="") return parser.parse_args() @@ -137,7 +139,7 @@ def collect_statistic(root: ET.Element): return devices, results, general_pass_rate, pass_rate_avg, general_test_count, trusted_ops -def create_summary(summary_root: ET.Element, output_folder: str): +def create_summary(summary_root: ET.Element, output_folder: str, report_tag: str): device_list, results, general_pass_rate, pass_rate_avg, general_test_count, trusted_ops = \ collect_statistic(summary_root) @@ -157,7 +159,7 @@ def create_summary(summary_root: ET.Element, output_folder: str): res_summary = template.render(ordered_ops=op_list, devices=device_list, results=results, timestamp=timestamp, general_pass_rate=general_pass_rate, pass_rate_avg=pass_rate_avg, verified_operations=verified_operations, trusted_ops=trusted_ops, - general_test_count=general_test_count) + general_test_count=general_test_count, report_tag=report_tag) report_path = os.path.join(output_folder, "report.html") with open(report_path, "w") as f: @@ -168,4 +170,4 @@ def create_summary(summary_root: ET.Element, output_folder: str): if __name__ == "__main__": args = parse_arguments() summary_root = merge_xmls(args.xml) - create_summary(summary_root, args.out) + create_summary(summary_root, args.out, args.report_tag) diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/template/report_template.html b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/template/report_template.html index 6eeeba16b1a..26f0923e144 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/template/report_template.html +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/template/report_template.html @@ -26,8 +26,9 @@ integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"> --> +
-

Operations coverage summary {{ timestamp }}

+

Operations coverage summary: {{report_tag}} {{ timestamp }}


@@ -42,7 +43,7 @@
- + {% for d in devices -%} From f84b25722ca68a5f4fdb3cc5b4ca3f7c1c95db05 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 18 May 2021 00:24:37 +0300 Subject: [PATCH 98/99] Removed legacy dependency on snippets (#5656) --- inference-engine/src/inference_engine/CMakeLists.txt | 1 - inference-engine/src/legacy_api/CMakeLists.txt | 3 +-- .../legacy_api/src/convert_function_to_cnn_network.cpp | 10 ---------- inference-engine/src/snippets/CMakeLists.txt | 9 +++++---- inference-engine/tests_deprecated/unit/CMakeLists.txt | 1 - 5 files changed, 6 insertions(+), 18 deletions(-) diff --git a/inference-engine/src/inference_engine/CMakeLists.txt b/inference-engine/src/inference_engine/CMakeLists.txt index 99dfa1b6401..68e0f131721 100644 --- a/inference-engine/src/inference_engine/CMakeLists.txt +++ b/inference-engine/src/inference_engine/CMakeLists.txt @@ -201,7 +201,6 @@ if(WIN32) endif() target_link_libraries(${TARGET_NAME}_s PRIVATE openvino::itt ${CMAKE_DL_LIBS} ${NGRAPH_LIBRARIES} - inference_engine_snippets inference_engine_transformations pugixml) target_compile_definitions(${TARGET_NAME}_s PUBLIC USE_STATIC_IE) diff --git a/inference-engine/src/legacy_api/CMakeLists.txt b/inference-engine/src/legacy_api/CMakeLists.txt index b03c329ca44..ca65d596e60 100644 --- a/inference-engine/src/legacy_api/CMakeLists.txt +++ b/inference-engine/src/legacy_api/CMakeLists.txt @@ -40,7 +40,6 @@ target_include_directories(${TARGET_NAME}_obj PRIVATE ${PUBLIC_HEADERS_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${IE_MAIN_SOURCE_DIR}/src/inference_engine # For CNNNetworkNGraphImpl - $ $ $ $ @@ -61,7 +60,7 @@ add_library(${TARGET_NAME} SHARED ie_add_vs_version_file(NAME ${TARGET_NAME} FILEDESCRIPTION "Inference Engine Legacy library") -target_link_libraries(${TARGET_NAME} PUBLIC inference_engine inference_engine_snippets +target_link_libraries(${TARGET_NAME} PUBLIC inference_engine PRIVATE pugixml openvino::itt ${NGRAPH_LIBRARIES} inference_engine_transformations) diff --git a/inference-engine/src/legacy_api/src/convert_function_to_cnn_network.cpp b/inference-engine/src/legacy_api/src/convert_function_to_cnn_network.cpp index 0b66531044a..6c76ac47e02 100644 --- a/inference-engine/src/legacy_api/src/convert_function_to_cnn_network.cpp +++ b/inference-engine/src/legacy_api/src/convert_function_to_cnn_network.cpp @@ -39,7 +39,6 @@ #include "legacy/ngraph_ops/rnn_sequence_ie.hpp" #include "legacy/ngraph_ops/lstm_sequence_ie.hpp" #include "legacy/ngraph_ops/gru_sequence_ie.hpp" -#include "snippets/op/subgraph.hpp" #include "exec_graph_info.hpp" #include "caseless.hpp" @@ -1979,15 +1978,6 @@ void convertFunctionToICNNNetwork(const std::shared_ptrparams[ExecGraphInfoSerialization::ORIGINAL_NAMES] = originalNames; } - if (auto subgraph = ::ngraph::as_type_ptr(layer)) { - std::string names = ""; - for (const auto& op : subgraph->get_body()->get_ordered_ops()) { - names += ", " + op->get_friendly_name(); - } - - cnnLayer->params["originalLayersNames"] += names; - } - std::string primitivesPriority = ::ngraph::getPrimitivesPriority(layer); if (!primitivesPriority.empty()) { cnnLayer->params["PrimitivesPriority"] = primitivesPriority; diff --git a/inference-engine/src/snippets/CMakeLists.txt b/inference-engine/src/snippets/CMakeLists.txt index 482f7e52bec..45e4b9bb352 100644 --- a/inference-engine/src/snippets/CMakeLists.txt +++ b/inference-engine/src/snippets/CMakeLists.txt @@ -52,7 +52,8 @@ ie_developer_export_targets(${TARGET_NAME}) # install -install(TARGETS ${TARGET_NAME} - RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core - ARCHIVE DESTINATION ${IE_CPACK_ARCHIVE_PATH} COMPONENT core - LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT core) +# TODO: uncomment once snippets are integrated into CPU plugin +# install(TARGETS ${TARGET_NAME} +# RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core +# ARCHIVE DESTINATION ${IE_CPACK_ARCHIVE_PATH} COMPONENT core +# LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT core) diff --git a/inference-engine/tests_deprecated/unit/CMakeLists.txt b/inference-engine/tests_deprecated/unit/CMakeLists.txt index 58b4c598fd8..18d7724add5 100644 --- a/inference-engine/tests_deprecated/unit/CMakeLists.txt +++ b/inference-engine/tests_deprecated/unit/CMakeLists.txt @@ -114,7 +114,6 @@ target_link_libraries(${TARGET_NAME} PRIVATE # dynamic libraries inference_engine_transformations inference_engine_lp_transformations - inference_engine_snippets ) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") From e41e25533d99d8126fb34d2b87218c463f62db9d Mon Sep 17 00:00:00 2001 From: Vladimir Zinoviev Date: Tue, 18 May 2021 00:59:01 +0300 Subject: [PATCH 99/99] [LPT] ConvolutionBackpropData support (#5313) * [LPT] ConvolutionBackpropData support * minor fixes * [Transformations] Legacy subtract precision keep * [LPT] ConvolutionBackpropData tests improvements * [LPT] ConvolutionBackpropData weights folding when can't be transformed * [LPT] CanBeTransformed unification and convolution weights folding * [LPT] GPU INT8 optimizations condition flag * [LPT] Concat precision predict improvement * [LPT] Turn off asymmetric quantization for Deconvolution on GPU * [LPT] Improvements from review * [LPT] Check if layer after concat isQuantized and require per-tensor quantize * [LPT] Improvement for Deconv->FQ pattern * [LPT] Commented failing tests --- .../src/cldnn_engine/cldnn_engine.cpp | 4 + .../convolution_backprop_data.hpp | 25 ++ .../low_precision/layer_transformation.hpp | 43 +-- .../include/low_precision/network_helper.hpp | 15 +- .../include/low_precision/transformer.hpp | 4 - .../weightable_layer_transformation.hpp | 2 +- .../low_precision_transformations/src/add.cpp | 1 + .../src/concat.cpp | 27 +- .../src/concat_multi_channels.cpp | 4 +- .../src/convolution.cpp | 22 +- .../src/convolution_backprop_data.cpp | 218 ++++++++++++ .../src/fake_quantize.cpp | 6 +- .../src/fuse_multiply_to_fake_quantize.cpp | 11 +- .../src/fuse_subtract_to_fake_quantize.cpp | 14 +- .../src/layer_transformation.cpp | 1 + .../src/network_helper.cpp | 100 ++++-- .../src/transformer.cpp | 22 +- .../src/weightable_layer_transformation.cpp | 30 +- .../src/mkldnn_plugin/mkldnn_plugin.cpp | 4 +- .../include/ngraph_ops/deconvolution_ie.hpp | 3 + .../src/ngraph_ops/deconvolution_ie.cpp | 40 ++- .../op_conversions/convert_convolutions.cpp | 2 + .../op_conversions/convert_subtract.cpp | 7 +- ...nvolution_backprop_data_transformation.cpp | 334 ++++++++++++++++++ .../convolution_qdq_transformation.cpp | 30 +- .../convolution_transformation.cpp | 22 +- .../group_convolution_transformation.cpp | 12 +- .../convert_deconvolution_test.cpp | 2 +- ...nvolution_backprop_data_transformation.cpp | 100 ++++++ ...nvolution_backprop_data_transformation.cpp | 103 ++++++ ...nvolution_backprop_data_transformation.hpp | 65 ++++ ...nvolution_backprop_data_transformation.cpp | 77 ++++ .../convolution_backprop_data_function.hpp | 54 +++ .../convolution_backprop_data_function.cpp | 149 ++++++++ ngraph/core/include/ngraph/op/convolution.hpp | 4 +- ngraph/core/include/ngraph/op/group_conv.hpp | 4 +- ngraph/core/src/op/convolution.cpp | 4 +- ngraph/core/src/op/group_conv.cpp | 2 +- 38 files changed, 1400 insertions(+), 167 deletions(-) create mode 100644 inference-engine/src/low_precision_transformations/include/low_precision/convolution_backprop_data.hpp create mode 100644 inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp create mode 100644 inference-engine/tests/functional/inference_engine/lp_transformations/convolution_backprop_data_transformation.cpp create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/convolution_backprop_data_transformation.cpp create mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/convolution_backprop_data_transformation.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/convolution_backprop_data_transformation.hpp create mode 100644 inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/convolution_backprop_data_transformation.cpp create mode 100644 inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/convolution_backprop_data_function.hpp create mode 100644 inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_backprop_data_function.cpp diff --git a/inference-engine/src/cldnn_engine/cldnn_engine.cpp b/inference-engine/src/cldnn_engine/cldnn_engine.cpp index 0bea81eface..4aa53beb1e5 100644 --- a/inference-engine/src/cldnn_engine/cldnn_engine.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_engine.cpp @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -381,6 +382,9 @@ InferenceEngine::CNNNetwork clDNNEngine::CloneAndTransformNetwork(const Inferenc .add(LayerTransformation::Params(params) .setSupportAsymmetricQuantization(false) .setSupport3DTensorOnActivations(false)) + .add(LayerTransformation::Params(params) + .setSupportAsymmetricQuantization(false) + .setDeconvolutionSpecificChannelsRatio(true)) // INT8 StridedSlice not supported .remove()); diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/convolution_backprop_data.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/convolution_backprop_data.hpp new file mode 100644 index 00000000000..d6bbe504dc6 --- /dev/null +++ b/inference-engine/src/low_precision_transformations/include/low_precision/convolution_backprop_data.hpp @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include "weightable_layer_transformation.hpp" + +namespace ngraph { +namespace pass { +namespace low_precision { + +class TRANSFORMATIONS_API ConvolutionBackpropDataTransformation : public WeightableLayerTransformation { +public: + ConvolutionBackpropDataTransformation(const Params& params); + void registerMatcherIn(GraphRewrite& pass, TransformationContext& context) const override; + bool transform(TransformationContext& context, ngraph::pattern::Matcher &m) const override; + bool canBeTransformed(const TransformationContext& context, std::shared_ptr op) const override; + bool isQuantized(std::shared_ptr layer) const noexcept override; +}; + +} // namespace low_precision +} // namespace pass +} // namespace ngraph diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp index 36b1293cd42..06a37ab8b22 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp @@ -45,6 +45,13 @@ class TRANSFORMATIONS_API DataPrecision { public: DataPrecision() : precision(element::undefined), min(0.f), max(0.f), hasZeroPoint(false) {} + explicit DataPrecision(const element::Type& precision) { + this->precision = precision; + min = getMinValue(precision, 256); + max = getMaxValue(precision, 256); + hasZeroPoint = false; + } + DataPrecision(const element::Type precision, const float min, const float max, const bool hasZeroPoint) : precision(precision), min(min), @@ -122,29 +129,6 @@ public: static element::Type getPrecision(const size_t /* quantizationLevels */, const bool signedInterval) { return signedInterval ? element::i8 : element::u8; } - - static float getMin(const size_t quantizationLevels, const bool signedInterval) { - if (quantizationLevels == 255) { - return signedInterval ? -127.0f : 0.0f; - } else if (quantizationLevels == 256) { - return signedInterval ? -128.0f : 0.0f; - } else { - // THROW_TRANSFORMATION_EXCEPTION << "quantization level " << quantizationLevels << " is not supported"; - // FIXME: not completed - return signedInterval ? -128.0f : 0.0f; - } - } - - static float getMax(const size_t quantizationLevels, const bool signedInterval) { - if ((quantizationLevels == 255) || (quantizationLevels == 256)) { - return signedInterval ? 127.0f : 255.0f; - } else { - // THROW_TRANSFORMATION_EXCEPTION << "quantization level " << quantizationLevels << " is not supported"; - // FIXME: not completed - // return quantizationLevels - 1.0; - return signedInterval ? 127.0f : 255.0f; - } - } }; inline bool operator==(const DataPrecision& value1, const DataPrecision& value2) { @@ -181,7 +165,8 @@ public: std::vector precisionsOnActivations = { element::u8, element::i8 }, std::vector precisionsOnWeights = { element::i8 }, element::Type deqPrecision = element::f32, - bool support3DTensorOnActivations = true) : + bool support3DTensorOnActivations = true, + bool deconvolutionSpecificChannelsRatio = false) : updatePrecisions(updatePrecisions), quantizedTensorAlignmentOnActivations(quantizedTensorAlignmentOnActivations), quantizedTensorAlignmentOnWeights(quantizedTensorAlignmentOnWeights), @@ -189,7 +174,8 @@ public: precisionsOnActivations(precisionsOnActivations), precisionsOnWeights(precisionsOnWeights), deqPrecision(deqPrecision), - support3DTensorOnActivations(support3DTensorOnActivations) { + support3DTensorOnActivations(support3DTensorOnActivations), + deconvolutionSpecificChannelsRatio(deconvolutionSpecificChannelsRatio) { if (precisionsOnActivations.size() == 0ul) { THROW_TRANSFORMATION_EXCEPTION << "precisions on activations are not specisifed"; } @@ -234,6 +220,11 @@ public: return *this; } + Params& setDeconvolutionSpecificChannelsRatio(const bool deconvolutionSpecificChannelsRatio) { + this->deconvolutionSpecificChannelsRatio = deconvolutionSpecificChannelsRatio; + return *this; + } + bool updatePrecisions; QuantizedTensorAlignment quantizedTensorAlignmentOnActivations; QuantizedTensorAlignment quantizedTensorAlignmentOnWeights; @@ -242,6 +233,7 @@ public: std::vector precisionsOnWeights; element::Type deqPrecision; bool support3DTensorOnActivations; + bool deconvolutionSpecificChannelsRatio; }; class PrecisionDetails { @@ -318,6 +310,7 @@ protected: std::vector precisionsOnWeights; element::Type deqPrecision; bool support3DTensorOnActivations; + bool deconvolutionSpecificChannelsRatio; // absolute value, used to determine quantization interval asymmetry float quantizationIntervalAsymmetryThreshold; diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp index 9846ef50d6a..8cf52a13fe2 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp @@ -109,7 +109,8 @@ public: const float max, const bool hasZeroPoint, const bool updatePrecision, - const element::Type deqPrecision = element::f32); + const element::Type deqPrecision = element::f32, + const size_t outChannelsShapeIndex = 0); static std::shared_ptr updateFakeQuantize( std::shared_ptr fq, @@ -183,7 +184,7 @@ public: static std::shared_ptr toScalarIfPossible(std::shared_ptr node); static std::shared_ptr fold_fake_quantize(const std::shared_ptr& fq); - static std::shared_ptr fold_fake_quantize(const std::shared_ptr& fq, const bool roundValues); + static std::shared_ptr fold_fake_quantize(const std::shared_ptr& fq, const bool roundValues, int outChannelsShapeIndex = 0); static FakeQuantizeDequantization foldDequantization(const std::shared_ptr& node, const size_t branchIndex, const bool inPlace = false); @@ -191,8 +192,16 @@ public: static std::shared_ptr fuseConvert(const std::shared_ptr& fakeQuantize); + static std::vector precisionIntersection( + const std::vector& v1, + const std::vector& v2) noexcept; + private: - static std::shared_ptr foldFakeQuantize(const std::shared_ptr& fq, const bool roundValues, const bool roundValuesWasSet); + static std::shared_ptr foldFakeQuantize( + const std::shared_ptr& fq, + const bool roundValues, + const bool roundValuesWasSet, + int outChannelsShapeIndex = 0); // 1 - on weights // 0 - weightable layer was not found diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/transformer.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/transformer.hpp index 7a10d1daeb1..8de3fba36d5 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/transformer.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/transformer.hpp @@ -303,10 +303,6 @@ private: std::map>> transformations, GraphRewrite& pass, TransformationContext& context); - - std::vector precisionIntersection( - const std::vector& v1, - const std::vector& v2) const noexcept; }; class TRANSFORMATIONS_API TypeRelaxedReplacer : public GraphRewrite { diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/weightable_layer_transformation.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/weightable_layer_transformation.hpp index 94b81f2b2af..aeb0a6d9abd 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/weightable_layer_transformation.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/weightable_layer_transformation.hpp @@ -22,7 +22,7 @@ public: bool isPrecisionPreserved(std::shared_ptr layer) const noexcept override; protected: - void decomposeFakeQuantizeForWeightsPath(std::shared_ptr weightableLayer) const; + void decomposeFakeQuantizeForWeightsPath(const std::shared_ptr& weightableLayer, size_t outChannelsShapeIndex = 0ul) const; static bool isGroup(const std::shared_ptr& node); static bool isDepthwise(const std::shared_ptr& node); diff --git a/inference-engine/src/low_precision_transformations/src/add.cpp b/inference-engine/src/low_precision_transformations/src/add.cpp index 85aef194893..915e87d2f60 100644 --- a/inference-engine/src/low_precision_transformations/src/add.cpp +++ b/inference-engine/src/low_precision_transformations/src/add.cpp @@ -42,6 +42,7 @@ std::shared_ptr replaceToSubtract(const std::shared_ptr& const auto parent = add->get_input_node_shared_ptr(dataBranchIndex); if (is_type(parent) || is_type(parent) || + is_type(parent) || (is_type(parent) && (is_type(parent->get_input_node_ptr(0)) || is_type(parent->get_input_node_ptr(1))))) { return nullptr; diff --git a/inference-engine/src/low_precision_transformations/src/concat.cpp b/inference-engine/src/low_precision_transformations/src/concat.cpp index 24cc5940c1b..4988e29b1e2 100644 --- a/inference-engine/src/low_precision_transformations/src/concat.cpp +++ b/inference-engine/src/low_precision_transformations/src/concat.cpp @@ -50,14 +50,14 @@ bool ConcatTransformation::transform(TransformationContext& context, ngraph::pat return false; } - DataPrecision dataPrecision = getDataPrecision(fq, QuantizationDetails::getDetails(fq), false); - if (dataPrecision.precision == ngraph::element::undefined) { + std::vector concatParentsChildrensPrecisions = precisionsOnActivations; + fillAvailablePrecisions(subgraph.quantizationLayers[0], concatParentsChildrensPrecisions); + if (concatParentsChildrensPrecisions.empty()) { return false; } - std::unordered_map dequantizations; for (size_t i = 0; i < subgraph.quantizationLayers.size(); ++i) { - const std::shared_ptr fq = ngraph::as_type_ptr(subgraph.quantizationLayers[i]); + fq = ngraph::as_type_ptr(subgraph.quantizationLayers[i]); if (fq == nullptr) { return false; } @@ -72,21 +72,20 @@ bool ConcatTransformation::transform(TransformationContext& context, ngraph::pat if (quantizationDetails.inputHighValues.size() != 1ul) { return false; } + std::vector fqChildrensPrecisions = precisionsOnActivations; + fillAvailablePrecisions(subgraph.quantizationLayers[i], fqChildrensPrecisions); + concatParentsChildrensPrecisions = NetworkHelper::precisionIntersection(concatParentsChildrensPrecisions, fqChildrensPrecisions); - const DataPrecision dataPrecision2 = getDataPrecision(subgraph.quantizationLayers[i]->shared_from_this(), quantizationDetails, false); - if (dataPrecision2.precision == ngraph::element::undefined) { + if (concatParentsChildrensPrecisions.empty()) { return false; } - - if (dataPrecision.precision != dataPrecision2.precision) { - // quantization levels are the same, difference can be in sign - // wider interval (precision) is preferable: use signed if least one interval is signed - dataPrecision = dataPrecision.precision.is_signed() ? dataPrecision : dataPrecision2; - } } - if (dataPrecision.precision == ngraph::element::undefined) { - return false; + DataPrecision dataPrecision; + if (std::find(concatParentsChildrensPrecisions.begin(), concatParentsChildrensPrecisions.end(), element::i8) != concatParentsChildrensPrecisions.end()) { + dataPrecision = DataPrecision(element::i8); + } else { + dataPrecision = DataPrecision(concatParentsChildrensPrecisions[0]); } std::vector quantizationLayersDetails; diff --git a/inference-engine/src/low_precision_transformations/src/concat_multi_channels.cpp b/inference-engine/src/low_precision_transformations/src/concat_multi_channels.cpp index 62d958d22b4..dc81d51cd71 100644 --- a/inference-engine/src/low_precision_transformations/src/concat_multi_channels.cpp +++ b/inference-engine/src/low_precision_transformations/src/concat_multi_channels.cpp @@ -27,7 +27,9 @@ bool ConcatMultiChannelsTransformation::isMultiChannel(const std::vector& concat : concatLayers) { const std::vector> children = getChildrenRecursivelyExceptPrecisionPreserved(concat); for (const std::shared_ptr& child : children) { - if (is_type(child.get())) { + if ((is_type(child.get()) || + is_type(child.get())) && + this->layerTransformationsManager->isQuantized(child)) { return false; } } diff --git a/inference-engine/src/low_precision_transformations/src/convolution.cpp b/inference-engine/src/low_precision_transformations/src/convolution.cpp index ff5ca944df5..6496ee4ee54 100644 --- a/inference-engine/src/low_precision_transformations/src/convolution.cpp +++ b/inference-engine/src/low_precision_transformations/src/convolution.cpp @@ -42,7 +42,27 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph auto convolution = m.get_match_root(); if (!canConvolutionBeTransformed(context, convolution)) { - return false; + auto weightInput = convolution->get_input_node_shared_ptr(1); + std::shared_ptr reshapeFromWeights = as_type_ptr(weightInput); + FakeQuantizeDequantization dequantization = reshapeFromWeights == nullptr ? + NetworkHelper::getDequantization(convolution, 1ul) : + NetworkHelper::getDequantization(reshapeFromWeights); + if (dequantization.empty()) { + const auto fqOnWeights = getFakeQuantizeOnWeights(convolution); + std::shared_ptr resultConstant = NetworkHelper::fold_fake_quantize(fqOnWeights); + if (reshapeFromWeights != nullptr) { + resultConstant = fold_reshape( + resultConstant, + reshapeFromWeights->input_value(1), + false); + } + if (as_type_ptr(resultConstant)) { + replace_node(weightInput, resultConstant); + } + } else { + NetworkHelper::foldDequantization(dequantization.multiply, 0, true); + } + return true; } convolution = NetworkHelper::separateInStandaloneBranch(convolution); diff --git a/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp b/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp new file mode 100644 index 00000000000..a73ee1de155 --- /dev/null +++ b/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp @@ -0,0 +1,218 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "low_precision/convolution_backprop_data.hpp" + +#include +#include +#include +#include +#include + +#include "low_precision/network_helper.hpp" +#include "low_precision/common/dequantization_op.hpp" + +namespace ngraph { +namespace pass { +namespace low_precision { + +ConvolutionBackpropDataTransformation::ConvolutionBackpropDataTransformation(const Params& params) : WeightableLayerTransformation(params) { +} + +void ConvolutionBackpropDataTransformation::registerMatcherIn(GraphRewrite &pass, TransformationContext &context) const { + addPattern( + pass, + context, + make_op_pattern({ make_op_label(), make_op_label() })); + addPattern( + pass, + context, + make_op_pattern({ make_op_label(), make_op_label() })); + addPattern( + pass, + context, + make_op_pattern( + { make_op_label(), make_op_label(), make_op_label() })); + addPattern( + pass, + context, + make_op_pattern( + { make_op_label(), make_op_label(), make_op_label() })); +} + +bool ConvolutionBackpropDataTransformation::isQuantized(std::shared_ptr layer) const noexcept { + if (deconvolutionSpecificChannelsRatio) { + size_t inputChannels = layer->get_input_shape(0)[1]; + size_t outputChannels = layer->get_output_shape(0)[1]; + if (inputChannels % 4 != 0 || outputChannels % 16 != 0) { + return false; + } + } + return WeightableLayerTransformation::isQuantized(layer, false); +} + +bool ConvolutionBackpropDataTransformation::transform(TransformationContext &context, ngraph::pattern::Matcher &m) const { + auto convolutionBackpropData = m.get_match_root(); + + if (!canBeTransformed(context, convolutionBackpropData)) { + auto weightsInput = convolutionBackpropData->get_input_node_shared_ptr(1); + std::shared_ptr reshapeFromWeights = as_type_ptr(weightsInput); + FakeQuantizeDequantization dequantization = reshapeFromWeights == nullptr ? + NetworkHelper::getDequantization(convolutionBackpropData, 1ul) : + NetworkHelper::getDequantization(reshapeFromWeights); + if (dequantization.empty()) { + const auto fqOnWeights = getFakeQuantizeOnWeights(convolutionBackpropData); + std::shared_ptr resultConstant = NetworkHelper::fold_fake_quantize(fqOnWeights); + if (reshapeFromWeights != nullptr) { + resultConstant = fold_reshape( + resultConstant, + reshapeFromWeights->input_value(1), + false); + } + if (as_type_ptr(resultConstant)) { + replace_node(weightsInput, resultConstant); + } + } else { + NetworkHelper::foldDequantization(dequantization.multiply, 0, true); + } + return true; + } + + convolutionBackpropData = NetworkHelper::separateInStandaloneBranch(convolutionBackpropData); + FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(convolutionBackpropData); + { + if (dequantization.subtract != nullptr) { + std::shared_ptr layer = dequantization.subtract; + ngraph::pass::low_precision::NetworkHelper::cleanRunTimeInfo(layer); + + NetworkHelper::optimizeSubtract(dequantization.subtract); + } + std::shared_ptr reducedConstant = as_type_ptr(dequantization.multiplyConstant); + std::shared_ptr newMultiplyAfterConst = std::make_shared( + reducedConstant->get_output_element_type(0), + Shape{ 1 }, + reducedConstant->cast_vector()[0]); + auto inputs = convolutionBackpropData->input_values(); + inputs[0] = dequantization.multiply->input_value(0); + const auto copyNode = convolutionBackpropData->copy_with_new_inputs(inputs); + + const auto relaxedConvolutionBackpropData = std::make_shared>( + *as_type_ptr(copyNode), + std::vector{deqPrecision, deqPrecision}, + std::vector{deqPrecision}); + + const auto newMultiplyAfter = std::make_shared>( + std::vector{ deqPrecision, deqPrecision }, + std::vector{ dequantization.multiply->get_output_element_type(0) }, + ngraph::op::TemporaryReplaceOutputType(relaxedConvolutionBackpropData, deqPrecision).get(), + ngraph::op::TemporaryReplaceOutputType(newMultiplyAfterConst, deqPrecision).get()); + + replace_node(convolutionBackpropData, newMultiplyAfter); + convolutionBackpropData = newMultiplyAfter->input_value(0).get_node_shared_ptr(); + inputs[0] = convolutionBackpropData->get_input_node_ptr(0)->input_value(0); + if (is_type(convolutionBackpropData->get_input_node_ptr(0))) { + auto newConvolution = convolutionBackpropData->copy_with_new_inputs(inputs); + replace_node(convolutionBackpropData, newConvolution); + convolutionBackpropData = newConvolution; + } + } + + { + decomposeFakeQuantizeForWeightsPath(convolutionBackpropData, 1ul); + + dequantization = NetworkHelper::getDequantization(convolutionBackpropData, 1ul); + + if (is_type(dequantization.data.get_node())) { + const std::shared_ptr fq = as_type_ptr(dequantization.data.get_node_shared_ptr()); + std::shared_ptr newFQ = NetworkHelper::fold_fake_quantize(fq, true); + NetworkHelper::copyInfo(fq, newFQ); + replace_node(fq, newFQ); + } + + std::shared_ptr multiplyFromWeights = as_type_ptr( + convolutionBackpropData->input_value(1).get_node_shared_ptr()); + std::shared_ptr subtractFromWeights = as_type_ptr(multiplyFromWeights->get_input_node_shared_ptr(0)); + + { + Shape newScaleShape = multiplyFromWeights->get_input_shape(1); + auto inputs = convolutionBackpropData->input_values(); + inputs[1] = multiplyFromWeights->input_value(0); + auto newMultiplyAfter = std::make_shared( + convolutionBackpropData->copy_with_new_inputs(inputs), + foldConvert( + fold_reshape( + multiplyFromWeights->input_value(1), + std::make_shared(element::u64, Shape{ newScaleShape.size() }, newScaleShape), + false), + convolutionBackpropData->get_output_element_type(0))); + replace_node(convolutionBackpropData, newMultiplyAfter); + convolutionBackpropData = newMultiplyAfter->input_value(0).get_node_shared_ptr(); + } + + if (subtractFromWeights != nullptr) { + // optimize zero point on weights + auto optimizedSubtract = NetworkHelper::optimizeSubtract(subtractFromWeights); + if (optimizedSubtract == nullptr) { + subtractFromWeights = nullptr; + } else { + subtractFromWeights = as_type_ptr(optimizedSubtract); + + const Shape weightsShape = subtractFromWeights->input(0).get_shape(); + Shape zeroPointShape(weightsShape.size(), 1ul); + zeroPointShape[1] = weightsShape[1]; + + auto zeroPointConstant = fold( + subtractFromWeights->get_input_node_shared_ptr(1), + std::make_shared(element::i32, Shape{zeroPointShape.size()}, zeroPointShape)); + replace_node(subtractFromWeights->get_input_node_shared_ptr(1), zeroPointConstant); + } + } + + std::shared_ptr convertFromWeights = + as_type_ptr( + subtractFromWeights == nullptr ? + multiplyFromWeights->get_input_node_shared_ptr(0) : + subtractFromWeights->get_input_node_shared_ptr(0)); + if (convertFromWeights != nullptr) { + auto inputs = convolutionBackpropData->input_values(); + inputs[1] = convolutionBackpropData->get_input_node_ptr(1)->input_value(0); + // remove Convert on weights + auto newConvolution = convolutionBackpropData->clone_with_new_inputs(inputs); + replace_node(convolutionBackpropData, newConvolution); + convolutionBackpropData = newConvolution; + } + } + std::shared_ptr finalDequantization = NetworkHelper::optimizeMultipliesAfter( + convolutionBackpropData->output(0).get_target_inputs().begin()->get_node()->shared_from_this()); + ngraph::copy_runtime_info({ convolutionBackpropData, finalDequantization }, finalDequantization); + updateOutput(context, finalDequantization, convolutionBackpropData); + + auto onWeights = convolutionBackpropData->get_input_node_shared_ptr(1); + if (is_type(onWeights)) { + onWeights = onWeights->get_input_node_shared_ptr(0); + } + + if (is_type(onWeights)) { + auto& rt = onWeights->get_rt_info(); + rt["DISABLED_CONSTANT_FOLDING"] = std::make_shared>(""); + } + + return true; +} + +bool ConvolutionBackpropDataTransformation::canBeTransformed(const TransformationContext& context, std::shared_ptr op) const { + if (deconvolutionSpecificChannelsRatio) { + size_t inputChannels = op->get_input_shape(0)[1]; + size_t outputChannels = op->get_output_shape(0)[1]; + if (inputChannels % 4 != 0 || outputChannels % 16 != 0) { + return false; + } + } + + return canConvolutionBeTransformed(context, op); +} + +} // namespace low_precision +} // namespace pass +} // namespace ngraph diff --git a/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp index 41b9851d5e3..53fe2702984 100644 --- a/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp @@ -20,7 +20,7 @@ void FakeQuantizeTransformation::registerMatcherIn(GraphRewrite& pass, Transform bool FakeQuantizeTransformation::transform(TransformationContext& context, ngraph::pattern::Matcher &m) const { std::shared_ptr layer = std::dynamic_pointer_cast(m.get_match_root()); - if (!NetworkHelper::isQuantizeSupported(layer)) { + if (!QuantizationDetails::outputLayoutIsSupported(layer)) { return false; } @@ -149,7 +149,9 @@ std::shared_ptr FakeQuantizeTransformation::fuseElementwis inputHighConst_f32 = fq::updateShape(fold(inputHighConst_f32, value), fakeQuantize->get_output_shape(0)); } else if (is_type(eltwise) && checkElementwise(eltwise)) { if (is_type(fq::getData(eltwise)) || - is_type(fq::getData(eltwise))) { + is_type(fq::getData(eltwise)) || + is_type(fq::getData(eltwise)) || + is_type(fq::getData(eltwise))) { return nullptr; } diff --git a/inference-engine/src/low_precision_transformations/src/fuse_multiply_to_fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fuse_multiply_to_fake_quantize.cpp index c1b7f4e907b..734d9abec43 100644 --- a/inference-engine/src/low_precision_transformations/src/fuse_multiply_to_fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fuse_multiply_to_fake_quantize.cpp @@ -45,11 +45,18 @@ bool FuseMultiplyToFakeQuantizeTransformation::transform(TransformationContext& const auto fakeQuantizeParent = fakeQuantize->get_input_node_shared_ptr(0); const size_t parentIndex = NetworkHelper::getParentOutputIndex(fakeQuantizeParent, fakeQuantize); + const auto inputLow = foldConvert(fakeQuantize->input_value(1), deqPrecision); + const auto inputHigh = foldConvert(fakeQuantize->input_value(2), deqPrecision); + NetworkHelper::copyInfo(fakeQuantize->get_input_node_shared_ptr(1), inputLow); + NetworkHelper::copyInfo(fakeQuantize->get_input_node_shared_ptr(2), inputHigh); + NetworkHelper::copyInfo(fakeQuantize->get_input_node_shared_ptr(3), outputLowConst_f32); + NetworkHelper::copyInfo(fakeQuantize->get_input_node_shared_ptr(4), outputHighConst_f32); + auto newFakeQuantize = std::make_shared>( opset1::FakeQuantize( fakeQuantizeParent->output(parentIndex), - foldConvert(fakeQuantize->input_value(1), deqPrecision), - foldConvert(fakeQuantize->input_value(2), deqPrecision), + inputLow, + inputHigh, outputLowConst_f32, outputHighConst_f32, fakeQuantize->get_levels()), diff --git a/inference-engine/src/low_precision_transformations/src/fuse_subtract_to_fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fuse_subtract_to_fake_quantize.cpp index 2e3f2e23d3f..8d8d9968802 100644 --- a/inference-engine/src/low_precision_transformations/src/fuse_subtract_to_fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fuse_subtract_to_fake_quantize.cpp @@ -45,11 +45,18 @@ bool FuseSubtractToFakeQuantizeTransformation::transform(TransformationContext& const auto fakeQuantizeParent = fakeQuantize->get_input_node_shared_ptr(0); const size_t parentIndex = NetworkHelper::getParentOutputIndex(fakeQuantizeParent, fakeQuantize); + const auto inputLow = foldConvert(fakeQuantize->input_value(1), deqPrecision); + const auto inputHigh = foldConvert(fakeQuantize->input_value(2), deqPrecision); + NetworkHelper::copyInfo(fakeQuantize->get_input_node_shared_ptr(1), inputLow); + NetworkHelper::copyInfo(fakeQuantize->get_input_node_shared_ptr(2), inputHigh); + NetworkHelper::copyInfo(fakeQuantize->get_input_node_shared_ptr(3), outputLowConst_f32); + NetworkHelper::copyInfo(fakeQuantize->get_input_node_shared_ptr(4), outputHighConst_f32); + auto newFakeQuantize = std::make_shared>( opset1::FakeQuantize( fakeQuantizeParent->output(parentIndex), - foldConvert(fakeQuantize->input_value(1), deqPrecision), - foldConvert(fakeQuantize->input_value(2), deqPrecision), + inputLow, + inputHigh, outputLowConst_f32, outputHighConst_f32, fakeQuantize->get_levels()), @@ -76,7 +83,8 @@ bool FuseSubtractToFakeQuantizeTransformation::canBeTransformed(const Transforma for (const auto& target : children) { const auto convolution = is_type(target.get_node()); const auto groupConvolution = is_type(target.get_node()); - if (convolution || groupConvolution) { + const auto convolutionBackpropData = is_type(target.get_node()); + if (convolution || groupConvolution || convolutionBackpropData) { return false; } } diff --git a/inference-engine/src/low_precision_transformations/src/layer_transformation.cpp b/inference-engine/src/low_precision_transformations/src/layer_transformation.cpp index 834aa6931c5..0fc0a9dc4fc 100644 --- a/inference-engine/src/low_precision_transformations/src/layer_transformation.cpp +++ b/inference-engine/src/low_precision_transformations/src/layer_transformation.cpp @@ -32,6 +32,7 @@ LayerTransformation::LayerTransformation(const Params& params) : precisionsOnWeights(params.precisionsOnWeights), deqPrecision(params.deqPrecision), support3DTensorOnActivations(params.support3DTensorOnActivations), + deconvolutionSpecificChannelsRatio(params.deconvolutionSpecificChannelsRatio), quantizationIntervalAsymmetryThreshold(0.002f), zeroThreshold(1.e-6f), minQuantizationLevels(2ul), diff --git a/inference-engine/src/low_precision_transformations/src/network_helper.cpp b/inference-engine/src/low_precision_transformations/src/network_helper.cpp index dbca7606e73..4a1e942e575 100644 --- a/inference-engine/src/low_precision_transformations/src/network_helper.cpp +++ b/inference-engine/src/low_precision_transformations/src/network_helper.cpp @@ -69,7 +69,8 @@ bool NetworkHelper::isConstantPath(const std::shared_ptr& op) { return is_type(node) || is_type(node) || is_type(node) || - is_type(node); + is_type(node) || + is_type(node); }; if (isNotConstantPathOperation(op)) { @@ -440,8 +441,11 @@ std::shared_ptr NetworkHelper::fold_fake_quantize(const std::shared_ptr NetworkHelper::fold_fake_quantize(const std::shared_ptr& fq, const bool roundValues) { - return foldFakeQuantize(fq, roundValues, true); +std::shared_ptr NetworkHelper::fold_fake_quantize( + const std::shared_ptr& fq, + const bool roundValues, + const int outChannelsShapeIndex) { + return foldFakeQuantize(fq, roundValues, true, outChannelsShapeIndex); } FakeQuantizeDequantization NetworkHelper::foldDequantization(const std::shared_ptr& node, const size_t branchIndex, const bool inPlace) { @@ -591,7 +595,8 @@ std::shared_ptr NetworkHelper::fuseConvert(const std::shar std::shared_ptr NetworkHelper::foldFakeQuantize( const std::shared_ptr& fq, const bool roundValuesArg, - const bool roundValuesWasSet) { + const bool roundValuesWasSet, + const int outChannelsShapeIndex) { if (is_type(fq->get_input_node_shared_ptr(0)) && is_type(fq->get_input_node_shared_ptr(1)) && is_type(fq->get_input_node_shared_ptr(2)) && @@ -630,10 +635,20 @@ std::shared_ptr NetworkHelper::foldFakeQuantize( if (constShape.empty() || constShape.size() > 5lu) { THROW_IE_LPT_EXCEPTION(*fq) << "Unexpected dimensions count " << constShape.size(); } + if (outChannelsShapeIndex != 0 && outChannelsShapeIndex != 1) { + THROW_IE_LPT_EXCEPTION(*fq) << "Unexpected outChannelsShapeIndex " << outChannelsShapeIndex; + } - // OIDHW - const size_t OC = constShape[0]; - const size_t IC = constShape.size() > 1lu ? constShape[1] : 1; + size_t OC; + size_t IC; + // OIDHW or IODHW + if (constShape.size() == 1) { + OC = constShape[0]; + IC = 1; + } else { + OC = constShape[outChannelsShapeIndex]; + IC = constShape[outChannelsShapeIndex == 0 ? 1 : 0]; + } const size_t D = constShape.size() > 4lu ? constShape[constShape.size() - 3] : 1; const size_t H = constShape.size() > 2lu ? constShape.size() == 3lu ? constShape[2] : constShape[constShape.size() - 2] : 1; const size_t W = constShape.size() > 3lu ? constShape[constShape.size() - 1] : 1; @@ -667,29 +682,35 @@ std::shared_ptr NetworkHelper::foldFakeQuantize( auto levels_1 = fq->get_levels() - 1.f; - //const size_t DHW = D * H * W; + const size_t DHW = D * H * W; const size_t IDHW = IC * D * H * W; const auto values = constant->cast_vector(); std::vector quantizedValues(OC * IC * D * H * W); for (size_t oc = 0; oc < OC; ++oc) { - for (size_t iidx = 0; iidx < IDHW; ++iidx) { - const float inputLow = inputLowValues[isInputLowBroadcasted ? 0 : oc]; - const float inputHigh = inputHighValues[isInputHighBroadcasted ? 0 : oc]; - const float outputLow = outputLowValues[isOutputLowBroadcasted ? 0 : oc]; - const float outputHigh = outputHighValues[isOutputHighBroadcasted ? 0 : oc]; + const float inputLow = inputLowValues[isInputLowBroadcasted ? 0 : oc]; + const float inputHigh = inputHighValues[isInputHighBroadcasted ? 0 : oc]; + const float outputLow = outputLowValues[isOutputLowBroadcasted ? 0 : oc]; + const float outputHigh = outputHighValues[isOutputHighBroadcasted ? 0 : oc]; + for (size_t ic = 0; ic < IC; ++ic) { + for (size_t iidx = 0; iidx < DHW; ++iidx) { + size_t idx; + if (outChannelsShapeIndex == 0) { + idx = oc * IDHW + ic * DHW + iidx; + } else { + idx = ic * IDHW + oc * DHW + iidx; + } - const size_t idx = oc * IDHW + iidx; - - if (values[idx] <= inputLow) { - quantizedValues[idx] = roundValues ? std::roundf(outputLow) : outputLow; - } else if (values[idx] > inputHigh) { - quantizedValues[idx] = roundValues ? std::roundf(outputHigh) : outputHigh; - } else { - const float value = std::roundf((values[idx] - inputLow) / (inputHigh - inputLow) * levels_1) / - levels_1 * (outputHigh - outputLow) + outputLow; - quantizedValues[idx] = roundValues ? std::roundf(value) : value; + if (values[idx] <= inputLow) { + quantizedValues[idx] = roundValues ? std::roundf(outputLow) : outputLow; + } else if (values[idx] > inputHigh) { + quantizedValues[idx] = roundValues ? std::roundf(outputHigh) : outputHigh; + } else { + const float value = std::roundf((values[idx] - inputLow) / (inputHigh - inputLow) * levels_1) / + levels_1 * (outputHigh - outputLow) + outputLow; + quantizedValues[idx] = roundValues ? std::roundf(value) : value; + } } } } @@ -818,7 +839,8 @@ std::tuple, std::shared_ptr> NetworkHelper::decompos const float max, const bool hasZeroPoint, const bool updatePrecision, - const element::Type deqPrecision) { + const element::Type deqPrecision, + const size_t outChannelsShapeIndex) { using std::make_shared; const auto outputLow = fq->input_value(3); @@ -898,7 +920,8 @@ std::tuple, std::shared_ptr> NetworkHelper::decompos newMax->output(0), fq->get_levels(), fq->get_auto_broadcast()), - true); + true, + outChannelsShapeIndex); NetworkHelper::copyInfo(fq, newFQ); std::shared_ptr convert2; @@ -1548,12 +1571,12 @@ bool NetworkHelper::checkZeroPoint(const std::shared_ptr& node, const Data if (is_type(node)) { const auto parent = node->get_input_node_shared_ptr(0); const auto intNode = is_type(parent) ? parent : node; - const auto intType = intNode->get_input_element_type(0); - if (intType == element::u8 || intType == element::i8) { - min = DataPrecision::getMinValue(intType, 256) - 0.5f; - max = DataPrecision::getMaxValue(intType, 256) + 0.5f; + const auto type = intNode->get_input_element_type(0); + if (type == element::u8 || type == element::i8) { + min = DataPrecision::getMinValue(type, 256) - 0.5f; + max = DataPrecision::getMaxValue(type, 256) + 0.5f; } else { - return false; + return type == element::f32 || type == element::f16; } auto subtract1input = node->get_input_node_shared_ptr(1); if (is_type(subtract1input)) { @@ -1595,6 +1618,23 @@ bool NetworkHelper::checkZeroPoint(const std::shared_ptr& node, const Data return true; } +std::vector NetworkHelper::precisionIntersection( + const std::vector& v1, + const std::vector& v2) noexcept { + std::vector v3; + + auto v1Copy = v1; + auto v2Copy = v2; + + std::sort(v1Copy.begin(), v1Copy.end()); + std::sort(v2Copy.begin(), v2Copy.end()); + + std::set_intersection(v1Copy.begin(), v1Copy.end(), + v2Copy.begin(), v2Copy.end(), + std::back_inserter(v3)); + return v3; +} + } // namespace low_precision } // namespace pass } // namespace ngraph diff --git a/inference-engine/src/low_precision_transformations/src/transformer.cpp b/inference-engine/src/low_precision_transformations/src/transformer.cpp index d8b484bcbce..4debb5868b6 100644 --- a/inference-engine/src/low_precision_transformations/src/transformer.cpp +++ b/inference-engine/src/low_precision_transformations/src/transformer.cpp @@ -34,6 +34,7 @@ #include "low_precision/avg_pool.hpp" #include "low_precision/clamp.hpp" #include "low_precision/convolution.hpp" +#include "low_precision/convolution_backprop_data.hpp" #include "low_precision/depth_to_space.hpp" #include "low_precision/fake_quantize.hpp" #include "low_precision/group_convolution.hpp" @@ -220,6 +221,7 @@ LowPrecisionTransformations LowPrecisionTransformer::getAllTransformations(const add(params). add(params). add(params). + add(params). add(params). add(params). add(params). @@ -338,6 +340,7 @@ TypeRelaxedReplacer::TypeRelaxedReplacer() { make_matcher_type_relaxed(this); make_matcher_type_relaxed(this); make_matcher_type_relaxed(this); + make_matcher_type_relaxed(this); make_matcher_type_relaxed(this); make_matcher_type_relaxed(this); make_matcher_type_relaxed(this); @@ -430,23 +433,6 @@ void LowPrecisionTransformer::transform(std::shared_ptr network) { network->validate_nodes_and_infer_types(); } -std::vector LowPrecisionTransformer::precisionIntersection( - const std::vector& v1, - const std::vector& v2) const noexcept { - std::vector v3; - - auto v1Copy = v1; - auto v2Copy = v2; - - std::sort(v1Copy.begin(), v1Copy.end()); - std::sort(v2Copy.begin(), v2Copy.end()); - - std::set_intersection(v1Copy.begin(), v1Copy.end(), - v2Copy.begin(), v2Copy.end(), - std::back_inserter(v3)); - return v3; -} - std::vector LowPrecisionTransformer::getPrecisionsOnActivations(const Node& op) const noexcept { const std::string operantionType = LowPrecisionTransformations::getType(op); const std::vector transformation = transformations.find(operantionType); @@ -456,7 +442,7 @@ std::vector LowPrecisionTransformer::getPrecisionsOnActivations(c std::vector precisions = transformation[0]->getPrecisionsOnActivations(); for (const auto& transform : transformation) { - precisions = precisionIntersection(precisions, transform->getPrecisionsOnActivations()); + precisions = NetworkHelper::precisionIntersection(precisions, transform->getPrecisionsOnActivations()); } return precisions; } diff --git a/inference-engine/src/low_precision_transformations/src/weightable_layer_transformation.cpp b/inference-engine/src/low_precision_transformations/src/weightable_layer_transformation.cpp index b3651cdf231..726fc893975 100644 --- a/inference-engine/src/low_precision_transformations/src/weightable_layer_transformation.cpp +++ b/inference-engine/src/low_precision_transformations/src/weightable_layer_transformation.cpp @@ -26,7 +26,7 @@ bool WeightableLayerTransformation::canConvolutionBeTransformed(const Transforma return false; } - if (updatePrecisions && !NetworkHelper::checkZeroPoint(dequantization.subtract)) { + if (!NetworkHelper::checkZeroPoint(dequantization.subtract)) { return false; } @@ -46,24 +46,10 @@ bool WeightableLayerTransformation::canConvolutionBeTransformed(const Transforma return false; } if (!NetworkHelper::checkZeroPoint(fqOnWeights, dataPrecision)) { - const std::shared_ptr resultConstant = NetworkHelper::fold_fake_quantize(fqOnWeights); - if (as_type_ptr(resultConstant)) { - replace_node(fqOnWeights, resultConstant); - } return false; } } else { if (!NetworkHelper::checkZeroPoint(dequantization.subtract)) { - const auto resultDequantization = NetworkHelper::foldDequantization(dequantization.multiply, 0, true); - if (resultDequantization.empty() && reshapeFromWeights) { - const auto foldedReshape = fold( - reshapeFromWeights->get_input_node_shared_ptr(0), - reshapeFromWeights->get_input_node_shared_ptr(1), - reshapeFromWeights->get_special_zero()); - if (is_type(foldedReshape)) { - replace_node(reshapeFromWeights, foldedReshape); - } - } return false; } } @@ -170,9 +156,11 @@ bool WeightableLayerTransformation::canBeTransformed(const TransformationContext return false; } - if ( // Check if all dimensions of scale except the first one (which is O-Output channels dimension) are all ones - (shape_size(constOutputShape) != constOutputShape[0]) || - ((constOutputShape[0] != 1ul) && (fqFromWeights->get_output_shape(0)[0] != constOutputShape[0]))) { + const size_t outChannelsShapeIndex = is_type(layer) ? 1ul : 0ul; + if ( // Check if all dimensions of scale except the output channels are all ones + (shape_size(constOutputShape) != constOutputShape[outChannelsShapeIndex]) || + ((constOutputShape[outChannelsShapeIndex] != 1ul) && + (fqFromWeights->get_output_shape(0)[outChannelsShapeIndex] != constOutputShape[outChannelsShapeIndex]))) { return false; } } else { @@ -256,7 +244,7 @@ bool WeightableLayerTransformation::isPrecisionPreserved(std::shared_ptr l return false; } -void WeightableLayerTransformation::decomposeFakeQuantizeForWeightsPath(std::shared_ptr node) const { +void WeightableLayerTransformation::decomposeFakeQuantizeForWeightsPath(const std::shared_ptr& node, const size_t outChannelsShapeIndex) const { const auto fq = getFakeQuantizeOnWeights(node); if (fq == nullptr) { return; @@ -270,7 +258,9 @@ void WeightableLayerTransformation::decomposeFakeQuantizeForWeightsPath(std::sha dataPrecision.min, dataPrecision.max, dataPrecision.hasZeroPoint, - updatePrecisions); + updatePrecisions, + element::f32, + outChannelsShapeIndex); std::shared_ptr fqOnWeights = std::get<0>(tuple); if (as_type_ptr(fqOnWeights) == nullptr) { diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index 32efc8d09ac..3ab7622ac91 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -328,7 +329,8 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { .add( LayerTransformation::Params(params).setPrecisionsOnActivations({ ngraph::element::u8 }).setSupportAsymmetricQuantization(true)) .addStandaloneCleanup( - LayerTransformation::Params(params).setPrecisionsOnActivations({ ngraph::element::u8 }))); + LayerTransformation::Params(params).setPrecisionsOnActivations({ ngraph::element::u8 })) + .remove()); transformer.transform(nGraphFunc); } diff --git a/inference-engine/src/transformations/include/ngraph_ops/deconvolution_ie.hpp b/inference-engine/src/transformations/include/ngraph_ops/deconvolution_ie.hpp index 96422f61e3b..3aa4a6492d1 100644 --- a/inference-engine/src/transformations/include/ngraph_ops/deconvolution_ie.hpp +++ b/inference-engine/src/transformations/include/ngraph_ops/deconvolution_ie.hpp @@ -29,6 +29,7 @@ public: const Strides& dilations, const CoordinateDiff& pads_begin, const CoordinateDiff& pads_end, + const element::Type output_type, const size_t& group = 1, const PadType& auto_pad = PadType::EXPLICIT, const CoordinateDiff& output_padding = {}, @@ -41,6 +42,7 @@ public: const Strides& dilations, const CoordinateDiff& pads_begin, const CoordinateDiff& pads_end, + const element::Type output_type, const size_t& group = 1, const PadType& auto_pad = PadType::EXPLICIT, const CoordinateDiff& output_padding = {}, @@ -79,6 +81,7 @@ protected: size_t m_group; CoordinateDiff m_output_padding; std::shared_ptr m_output_shape; + element::Type m_output_type; }; } // namespace op diff --git a/inference-engine/src/transformations/src/ngraph_ops/deconvolution_ie.cpp b/inference-engine/src/transformations/src/ngraph_ops/deconvolution_ie.cpp index ef9bc90bd1e..e8940700dbe 100644 --- a/inference-engine/src/transformations/src/ngraph_ops/deconvolution_ie.cpp +++ b/inference-engine/src/transformations/src/ngraph_ops/deconvolution_ie.cpp @@ -13,6 +13,7 @@ #include "ngraph/util.hpp" #include "ngraph/validation_util.hpp" #include "ngraph/opsets/opset1.hpp" +#include "ngraph_ops/type_relaxed.hpp" using namespace std; using namespace ngraph; @@ -25,6 +26,7 @@ op::DeconvolutionIE::DeconvolutionIE(const Output& data, const Strides& dilations, const CoordinateDiff& pads_begin, const CoordinateDiff& pads_end, + const element::Type output_type, const size_t& group, const PadType& auto_pad, const CoordinateDiff& output_padding, @@ -37,7 +39,8 @@ op::DeconvolutionIE::DeconvolutionIE(const Output& data, , m_auto_pad(auto_pad) , m_group(group) , m_output_padding(output_padding) - , m_output_shape(output_shape) { + , m_output_shape(output_shape) + , m_output_type(output_type) { constructor_validate_and_infer_types(); } @@ -48,6 +51,7 @@ op::DeconvolutionIE::DeconvolutionIE(const Output& data, const Strides& dilations, const CoordinateDiff& pads_begin, const CoordinateDiff& pads_end, + const element::Type output_type, const size_t& group, const PadType& auto_pad, const CoordinateDiff& output_padding, @@ -60,7 +64,8 @@ op::DeconvolutionIE::DeconvolutionIE(const Output& data, , m_auto_pad(auto_pad) , m_group(group) , m_output_padding(output_padding) - , m_output_shape(output_shape) { + , m_output_shape(output_shape) + , m_output_type(output_type) { constructor_validate_and_infer_types(); } @@ -81,13 +86,32 @@ void op::DeconvolutionIE::validate_and_infer_types() { } Output conv; if (m_output_shape) { - conv = std::make_shared(input_value(0), weights, m_output_shape, - m_strides, m_pads_begin, m_pads_end, m_dilations, m_auto_pad, m_output_padding); + conv = std::make_shared>( + std::vector{ element::f32, element::f32 }, + std::vector{ element::f32 }, + ngraph::op::TemporaryReplaceOutputType(input_value(0), element::f32).get(), + ngraph::op::TemporaryReplaceOutputType(weights, element::f32).get(), + m_output_shape, + m_strides, + m_pads_begin, + m_pads_end, + m_dilations, + m_auto_pad, + m_output_padding); } else { - conv = std::make_shared(input_value(0), weights, - m_strides, m_pads_begin, m_pads_end, m_dilations, m_auto_pad, m_output_padding); + conv = std::make_shared>( + std::vector{ element::f32, element::f32 }, + std::vector{ element::f32 }, + ngraph::op::TemporaryReplaceOutputType(input_value(0), element::f32).get(), + ngraph::op::TemporaryReplaceOutputType(weights, element::f32).get(), + m_strides, + m_pads_begin, + m_pads_end, + m_dilations, + m_auto_pad, + m_output_padding); } - set_output_type(0, conv.get_element_type(), conv.get_partial_shape()); + set_output_type(0, m_output_type, conv.get_partial_shape()); } shared_ptr op::DeconvolutionIE::clone_with_new_inputs(const ngraph::OutputVector &new_args) const { @@ -99,6 +123,7 @@ shared_ptr op::DeconvolutionIE::clone_with_new_inputs(const ngraph::Output m_dilations, m_pads_begin, m_pads_end, + m_output_type, m_group, m_auto_pad, m_output_padding, @@ -111,6 +136,7 @@ shared_ptr op::DeconvolutionIE::clone_with_new_inputs(const ngraph::Output m_dilations, m_pads_begin, m_pads_end, + m_output_type, m_group, m_auto_pad, m_output_padding, diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/convert_convolutions.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/convert_convolutions.cpp index 5b7965762a5..1f0fb32ae6b 100644 --- a/inference-engine/src/transformations/src/transformations/op_conversions/convert_convolutions.cpp +++ b/inference-engine/src/transformations/src/transformations/op_conversions/convert_convolutions.cpp @@ -113,6 +113,7 @@ ngraph::pass::ConvertDeconvolution::ConvertDeconvolution() { deconv->get_dilations(), deconv->get_pads_begin(), deconv->get_pads_end(), + deconv->get_output_element_type(0), 1 /* groups */, deconv->get_auto_pad(), deconv->get_output_padding(), @@ -158,6 +159,7 @@ ngraph::pass::ConvertGroupDeconvolution::ConvertGroupDeconvolution() { gconv->get_dilations(), gconv->get_pads_begin(), gconv->get_pads_end(), + gconv->get_output_element_type(0), group, gconv->get_auto_pad(), gconv->get_output_padding(), diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/convert_subtract.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/convert_subtract.cpp index 7080688b09c..b5507ee205f 100644 --- a/inference-engine/src/transformations/src/transformations/op_conversions/convert_subtract.cpp +++ b/inference-engine/src/transformations/src/transformations/op_conversions/convert_subtract.cpp @@ -38,11 +38,14 @@ ngraph::pass::ConvertSubtract::ConvertSubtract() { const std::shared_ptr child = subChildren.begin()->get_node()->shared_from_this(); if (child != nullptr) { if (is_type(child) || + is_type(child) || is_type(child) || + is_type(child) || is_type(child) || - (is_type(child) && + (is_type(child) && (child->output(0).get_target_inputs().size() == 1ul) && - is_type(child->output(0).get_target_inputs().begin()->get_node()->shared_from_this()))) { + (is_type(child->output(0).get_target_inputs().begin()->get_node()->shared_from_this()) || + is_type(child->output(0).get_target_inputs().begin()->get_node()->shared_from_this())))) { const auto input1Type = sub->input(0).get_element_type(); const auto input2Type = sub->input(1).get_element_type(); if (((input1Type == element::u8) && (input2Type == element::u8)) || diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_backprop_data_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_backprop_data_transformation.cpp new file mode 100644 index 00000000000..283adb5bf45 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_backprop_data_transformation.cpp @@ -0,0 +1,334 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "layer_transformation.hpp" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" +#include "simple_low_precision_transformer.hpp" +#include "lpt_ngraph_functions/convolution_backprop_data_function.hpp" + +using namespace testing; +using namespace ngraph; +using namespace ngraph::pass; + +class ConvolutionBackpropDataTransformationTestValues { +public: + class Actual { + public: + ngraph::element::Type precisionBeforeDequantization; + ngraph::builder::subgraph::DequantizationOperations dequantizationOnActivations; + builder::subgraph::FakeQuantizeOnWeights fakeQuantizeOnWeights; + builder::subgraph::DequantizationOperations dequantizationOnWeights; + std::shared_ptr weights; + + Actual() = default; + Actual( + const ngraph::element::Type& precisionBeforeDequantization, + const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnActivations, + const builder::subgraph::FakeQuantizeOnWeights& fakeQuantizeOnWeights, + const std::shared_ptr& weights) : + precisionBeforeDequantization(precisionBeforeDequantization), + dequantizationOnActivations(dequantizationOnActivations), + fakeQuantizeOnWeights(fakeQuantizeOnWeights), + weights(weights) {} + Actual( + const ngraph::element::Type& precisionBeforeDequantization, + const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnActivations, + const builder::subgraph::DequantizationOperations& dequantizationOnWeights, + const std::shared_ptr& weights) : + precisionBeforeDequantization(precisionBeforeDequantization), + dequantizationOnActivations(dequantizationOnActivations), + dequantizationOnWeights(dequantizationOnWeights), + weights(weights) {} + }; + + class Expected { + public: + ngraph::element::Type precisionBeforeDequantization; + ngraph::builder::subgraph::DequantizationOperations dequantizationOnActivations; + builder::subgraph::DequantizationOperations dequantizationOnWeights; + ngraph::builder::subgraph::DequantizationOperations dequantizationAfter; + std::shared_ptr weights; + bool transformed; + }; + + ngraph::pass::low_precision::LayerTransformation::Params params; + Actual actual; + Expected expected; +}; + +typedef std::tuple< + element::Type, + ngraph::Shape, + ConvolutionBackpropDataTransformationTestValues> ConvolutionBackpropDataTransformationParams; + +class ConvolutionBackpropDataTransformation : public LayerTransformation, public testing::WithParamInterface { +public: + void SetUp() override { + const auto netPrecision = std::get<0>(GetParam()); + const auto inputShape = std::get<1>(GetParam()); + auto outputShape = inputShape; + outputShape[1] /= 4; + outputShape[2] *= 2; + outputShape[3] *= 2; + auto testValues = std::get<2>(GetParam()); + + std::shared_ptr actualWeights = pass::low_precision::fold( + testValues.actual.weights, + opset1::Constant::create( + element::i64, + Shape{inputShape.size()}, + Shape{inputShape[1], outputShape[1], 1, 1})); + if (!testValues.actual.fakeQuantizeOnWeights.empty()) { + actualWeights = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getWeights( + outputShape, + netPrecision, + testValues.actual.fakeQuantizeOnWeights, + as_type_ptr(actualWeights)); + } else { + actualWeights = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getWeights( + outputShape, + netPrecision, + testValues.actual.dequantizationOnWeights, + as_type_ptr(actualWeights)); + } + + actualFunction = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getOriginal( + testValues.actual.precisionBeforeDequantization, + netPrecision, + inputShape, + outputShape, + testValues.actual.dequantizationOnActivations, + actualWeights); + + SimpleLowPrecisionTransformer transform; + transform.add(testValues.params); + transform.transform(actualFunction); + std::shared_ptr refWeights = pass::low_precision::fold( + testValues.expected.weights, + opset1::Constant::create( + element::i64, + Shape{inputShape.size()}, + Shape{inputShape[1], outputShape[1], 1, 1})); + + if (!testValues.expected.transformed) { + refWeights = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getWeights( + outputShape, + netPrecision, + testValues.actual.fakeQuantizeOnWeights, + as_type_ptr(refWeights)); + } else { + refWeights = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getWeights( + outputShape, + netPrecision, + testValues.expected.dequantizationOnWeights, + as_type_ptr(refWeights)); + } + + referenceFunction = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getReference( + testValues.expected.precisionBeforeDequantization, + netPrecision, + inputShape, + outputShape, + testValues.expected.dequantizationOnActivations, + refWeights, + testValues.expected.dequantizationAfter); + } + + static std::string getTestCaseName(testing::TestParamInfo obj) { + const auto netPrecision = std::get<0>(obj.param); + auto inputShape = std::get<1>(obj.param); + ConvolutionBackpropDataTransformationTestValues testValues = std::get<2>(obj.param); + + std::ostringstream result; + result << toString(testValues.params) << "_" << + netPrecision << "_" << + inputShape << "_" << + testValues.actual.precisionBeforeDequantization << "_" << + testValues.actual.dequantizationOnActivations << "_" << + testValues.actual.dequantizationOnWeights << "_" << + testValues.actual.fakeQuantizeOnWeights << "_" <<"_weights_" << + testValues.actual.weights->get_element_type() << "_" << "{ " << + testValues.actual.weights->cast_vector()[0] << " }_"; + return result.str(); + } +}; + +TEST_P(ConvolutionBackpropDataTransformation, CompareFunctions) { + actualFunction->validate_nodes_and_infer_types(); + auto res = compare_functions(referenceFunction, actualFunction, true, true, true); + ASSERT_TRUE(res.first) << res.second; +} + +const std::vector netPrecisions = { + element::f32, + element::f16 +}; + +const std::vector shapes = { + ngraph::Shape({ 1, 8, 16, 16 }) +}; + +const std::vector testValues = { + // with zero point + { + LayerTransformation::createParamsU8I8(), + // ActualValues + { + ngraph::element::u8, + {{ngraph::element::f32}, { 128.f }, { 0.02f }}, + { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }) + }, + // ExpectedValues + { + ngraph::element::u8, + {{}, { { 128.f }, ngraph::element::f32, {}, false }, {}}, + {}, + {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 1, 1, 1, 1 }}}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ -125.f }), + true + } + }, + // updatePrecisions = false + { + LayerTransformation::createParamsU8I8().setUpdatePrecisions(false), + // ActualValues + { + ngraph::element::u8, + {{ngraph::element::f32}, { 128.f }, { 0.02f }}, + { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }) + }, + // ExpectedValues + { + ngraph::element::u8, + {{}, { { 128.f }, ngraph::element::f32, {}, false }, {}}, + {}, + {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 1, 1, 1, 1 }}}, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -125.f }), + true + } + }, + // QDq version + { + LayerTransformation::createParamsU8I8(), + // ActualValues + { + ngraph::element::u8, + {{ngraph::element::f32}, { 128.f }, { 0.02f }}, + {{ngraph::element::f32}, { 2.f }, { 0.01f }}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }) + }, + // ExpectedValues + { + ngraph::element::u8, + {{}, { { 128.f }, ngraph::element::f32, {}, false }, {}}, + {{}, { { 2.f }, ngraph::element::f32, {1, 2, 1, 1}, true, 1ul, element::i8, false, { "DISABLED_CONSTANT_FOLDING" } }, {}}, + {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 1 }}}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }), + true + } + }, + // without zero point + { + LayerTransformation::createParamsU8I8(), + // ActualValues + { + ngraph::element::u8, + {{ngraph::element::f32}, {}, { 0.02f }}, + { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }) + }, + // ExpectedValues + { + ngraph::element::u8, + {}, + {}, + {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 1, 1, 1, 1 }}}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ -125.f }), + true + } + }, + // QDq version + { + LayerTransformation::createParamsU8I8(), + // ActualValues + { + ngraph::element::u8, + {{ngraph::element::f32}, {}, { 0.02f }}, + {{ngraph::element::f32}, {}, { 0.01f }}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }) + }, + // ExpectedValues + { + ngraph::element::u8, + {}, + {}, + {{}, {}, {{ 0.0002f }, ngraph::element::f32, {1}}}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }), + true + } + }, + // per-channel dequantization with the same values + { + LayerTransformation::createParamsU8I8(), + // ActualValues + { + ngraph::element::u8, + {{ngraph::element::f32}, {}, { std::vector{0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f} }}, + { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }) + }, + // ExpectedValues + { + ngraph::element::u8, + {}, + {}, + {{}, {}, {{ 0.0002f }, ngraph::element::f32, { 1, 1, 1, 1 }}}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ -125.f }), + true + } + }, + // per-channel dequantization with different values + { + LayerTransformation::createParamsU8I8(), + // ActualValues + { + ngraph::element::u8, + {{ngraph::element::f32}, {}, { std::vector{0.02f, 0.01f, 0.02f, 0.01f, 0.02f, 0.01f, 0.02f, 0.01f} }}, + { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }) + }, + // ExpectedValues + { + ngraph::element::u8, + {{ngraph::element::f32}, {}, { std::vector{0.02f, 0.01f, 0.02f, 0.01f, 0.02f, 0.01f, 0.02f, 0.01f} }}, + {}, + {}, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + true + } + }, +}; + +INSTANTIATE_TEST_CASE_P( + smoke_LPT, + ConvolutionBackpropDataTransformation, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(shapes), + ::testing::ValuesIn(testValues)), + ConvolutionBackpropDataTransformation::getTestCaseName); diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_qdq_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_qdq_transformation.cpp index c52606641c4..75b1d965e53 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_qdq_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_qdq_transformation.cpp @@ -231,7 +231,7 @@ const std::vector testValues = { } }, - // Actual & Transformed: + // Actual: // // Parameter Constant Constant Constant // |U8 |U8 |FP32 |I8 @@ -246,6 +246,22 @@ const std::vector testValues = { // \FP32 /FP32 // \ / // Convolution + // + // Transformed: + // + // Parameter Constant + // |U8 |U8 + // | | + // Convert Convert + // \FP32 /FP32 + // \ / + // Subtract Constant + // \FP32 /FP32 + // \ / + // Multiply Constant + // \FP32 /FP32 + // \ / + // Convolution { LayerTransformation::createParamsU8I8().setSupportAsymmetricQuantization(true), // ActualValues @@ -262,8 +278,8 @@ const std::vector testValues = { { ngraph::element::u8, {{ngraph::element::f32}, { {127.f}, element::f32, {}, false, 1ul, element::u8, true }, { 0.02f }}, - {{ngraph::element::f32}, { {127.f}, element::f32, {}, false, 1ul, element::i8, true }, { 0.03f }}, - { std::vector{ 2.f }, ngraph::element::f32}, + {}, + { std::vector{ -3.75f }, ngraph::element::f32}, {}, ngraph::element::f32, {} @@ -434,12 +450,8 @@ const std::vector testValues = { { {1000.f}, element::f32, {}, false }, { {0.02f}, element::f32, {}, false } }, - { - { ngraph::element::f32, false }, - { {127.f}, element::f32, {}, false }, - { {0.03f}, element::f32, {}, false } - }, - { std::vector{ 2.f }, ngraph::element::i8}, + {}, + { std::vector{ -3.75f }, ngraph::element::f32}, {}, ngraph::element::f32, {} diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_transformation.cpp index 4ccbc8f412a..8c2d42dfbf3 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/convolution_transformation.cpp @@ -160,8 +160,8 @@ const std::vector testValues = { { ngraph::element::u8, {{ ngraph::element::f32 }, { 128.f }, { 0.02f }}, - op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), - { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + {}, ngraph::element::f32, {} } @@ -288,13 +288,13 @@ const std::vector testValues = { {{ 128.f, 0.f, 128.f }, ngraph::element::f32, { 1, 3, 1, 1 }}, {{ 0.02f, 0.01f, 0.03f }, ngraph::element::f32, {1, 3, 1, 1}} }, - op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), - { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + {}, ngraph::element::f32, {} } }, - // dequantization in second dimension + // float input { LayerTransformation::createParamsU8I8(), // ActualValues @@ -316,8 +316,8 @@ const std::vector testValues = { {{ 128.f }, ngraph::element::f32, { 1, 1, 1, 1 }}, {{ 0.02f }, ngraph::element::f32, {1, 1, 1, 1}} }, - op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), - { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + {}, ngraph::element::f32, {} } @@ -356,8 +356,8 @@ const std::vector testValues = { { ngraph::element::f32, {{}, {}, { {0.02f}, element::f32 }}, - op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), - { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + {}, ngraph::element::f32, {} } @@ -396,8 +396,8 @@ const std::vector testValues = { { ngraph::element::u8, {{element::f32}, { 1000.f }, { {0.02f}, element::f32 }}, - op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), - { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + {}, ngraph::element::f32, {} } diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp index 7ba3252999e..d90999bb8cc 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp @@ -160,8 +160,8 @@ const std::vector testValues = { { ngraph::element::u8, {{ ngraph::element::f32 }, { 128.f }, { 0.02f }}, - op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), - { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + {}, {}, ngraph::element::f32, {} @@ -286,8 +286,8 @@ const std::vector testValues = { { ngraph::element::f32, {{}, {}, { 0.02f }}, - op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), - { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + {}, {}, ngraph::element::f32, {} @@ -459,8 +459,8 @@ const std::vector testValues = { { ngraph::element::f32, {{}, {}, { 0.02f }}, - op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), - { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.27f }, { 1.27f } }, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ -1.25f }), + {}, {}, ngraph::element::f32, {} diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_deconvolution_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_deconvolution_test.cpp index afe15697f0b..51f60318f18 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_deconvolution_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_deconvolution_test.cpp @@ -60,7 +60,7 @@ private: auto input = std::make_shared(ngraph::element::f32, input_shape); auto weights = ngraph::opset1::Constant::create(ngraph::element::f32, weights_shape, {1}); auto conv = std::make_shared(input, weights, ngraph::Strides(spatial_dims, 1), ngraph::Strides(spatial_dims, 1), - ngraph::CoordinateDiff(spatial_dims, 0), ngraph::CoordinateDiff(spatial_dims, 0)); + ngraph::CoordinateDiff(spatial_dims, 0), ngraph::CoordinateDiff(spatial_dims, 0), ngraph::element::f32); return std::make_shared(ngraph::NodeVector{conv}, ngraph::ParameterVector{input}); } diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/convolution_backprop_data_transformation.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/convolution_backprop_data_transformation.cpp new file mode 100644 index 00000000000..64ce304a247 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/convolution_backprop_data_transformation.cpp @@ -0,0 +1,100 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "low_precision_transformations/convolution_backprop_data_transformation.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +namespace { +const std::vector netPrecisions = { + ngraph::element::f32 +}; + +const std::vector trasformationParamValues = { + LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(true), + LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(false) +}; + +const std::vector params = { + // FQ on weights + // with zero point + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { -12.7f }, { 12.8f }}, + {255ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 254.f }, { -127.f }, { 127.f }}, + "", + "" + }, + // without zero point + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { 0.f }, { 25.5f }}, + {255ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 254.f }, { 0.f }, { 25.4f }}, + "", + "" + }, + // with incorrect zero point on activations + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 5.f }, { 6.f }, { 5.f }, { 6.f }}, + {255ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 254.f }, { 0.f }, { 25.4f }}, + "", + "" + }, + // with incorrect zero point on weights + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { 0.f }, { 25.5f }}, + {255ul, ngraph::Shape{1, 1, 1, 1}, { 5.f }, { 6.f }, { 5.f }, { 6.f }}, + "", + "" + }, + // QDq on weights + // with zero point + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { -12.7f }, { 12.8f }}, + {{ngraph::element::f32}, { {12.f}, ngraph::element::f32, {}, false }, { {4.f}, ngraph::element::f32, {}, false }}, + "", + "" + }, + // without zero point + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { 0.f }, { 25.5f }}, + {{ngraph::element::f32}, {}, { {4.f}, ngraph::element::f32, {}, false }}, + "", + "" + }, + // with incorrect zero point on activations + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 5.f }, { 6.f }, { 5.f }, { 6.f }}, + {{ngraph::element::f32}, { {12.f}, ngraph::element::f32, {}, false }, { {4.f}, ngraph::element::f32, {}, false }}, + "", + "" + }, + // with incorrect zero point on weights + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { -12.7f }, { 12.8f }}, + {{ngraph::element::f32}, { {1000.f}, ngraph::element::f32, {}, false }, { {4.f}, ngraph::element::f32, {}, false }}, + "", + "" + } +}; + +const std::vector inputShapes = { + { 1, 8, 16, 16 } +}; + +const std::vector outputShapes = { + { 16, 16 } +}; + +INSTANTIATE_TEST_CASE_P(smoke_LPT, ConvolutionBackpropDataTransformation, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(inputShapes), + ::testing::ValuesIn(outputShapes), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::ValuesIn(trasformationParamValues), + ::testing::ValuesIn(params)), + ConvolutionBackpropDataTransformation::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/convolution_backprop_data_transformation.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/convolution_backprop_data_transformation.cpp new file mode 100644 index 00000000000..d33e3c42f9e --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/convolution_backprop_data_transformation.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "low_precision_transformations/convolution_backprop_data_transformation.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +namespace { +const std::vector netPrecisions = { + ngraph::element::f32, + ngraph::element::f16 +}; + +const std::vector trasformationParamValues = { + LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(true), + LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(false) +}; + +const std::vector params = { + // FQ on weights + // with zero point + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { -12.7f }, { 12.8f }}, + {255ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 254.f }, { -127.f }, { 127.f }}, + "", + "" + }, + // without zero point + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { 0.f }, { 25.5f }}, + {255ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 254.f }, { 0.f }, { 25.4f }}, + "", + "" + }, + // TODO: check fails in CI +// // with incorrect zero point on activations +// { +// {256ul, ngraph::Shape{1, 1, 1, 1}, { 5.f }, { 6.f }, { 5.f }, { 6.f }}, +// {255ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 254.f }, { 0.f }, { 25.4f }}, +// "", +// "" +// }, +// // with incorrect zero point on weights +// { +// {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { 0.f }, { 25.5f }}, +// {255ul, ngraph::Shape{1, 1, 1, 1}, { 5.f }, { 6.f }, { 5.f }, { 6.f }}, +// "", +// "" +// }, + // QDq on weights + // with zero point + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { -12.7f }, { 12.8f }}, + {{ngraph::element::f32}, { {12.f}, ngraph::element::f32, {}, false }, { {4.f}, ngraph::element::f32, {}, false }}, + "", + "" + }, + // without zero point + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { 0.f }, { 25.5f }}, + {{ngraph::element::f32}, {}, { {4.f}, ngraph::element::f32, {}, false }}, + "", + "" + }, + // with incorrect zero point on activations + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 5.f }, { 6.f }, { 5.f }, { 6.f }}, + {{ngraph::element::f32}, { {12.f}, ngraph::element::f32, {}, false }, { {4.f}, ngraph::element::f32, {}, false }}, + "", + "" + }, + // with incorrect zero point on weights + { + {256ul, ngraph::Shape{1, 1, 1, 1}, { 0.f }, { 255.f }, { -12.7f }, { 12.8f }}, + {{ngraph::element::f32}, { {1000.f}, ngraph::element::f32, {}, false }, { {4.f}, ngraph::element::f32, {}, false }}, + "", + "" + } +}; + +const std::vector inputShapes = { + { 1, 8, 16, 16 }, + { 1, 32, 16, 16 } +}; + +const std::vector outputShapes = { + { 16, 16 } +}; + +INSTANTIATE_TEST_CASE_P(smoke_LPT, ConvolutionBackpropDataTransformation, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(inputShapes), + ::testing::ValuesIn(outputShapes), + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(trasformationParamValues), + ::testing::ValuesIn(params)), + ConvolutionBackpropDataTransformation::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/convolution_backprop_data_transformation.hpp b/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/convolution_backprop_data_transformation.hpp new file mode 100644 index 00000000000..39d5ea58391 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/low_precision_transformations/convolution_backprop_data_transformation.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + + +#include "shared_test_classes/base/low_precision_transformations/layer_transformation.hpp" +#include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp" +#include "lpt_ngraph_functions/common/fake_quantize_on_weights.hpp" +#include "lpt_ngraph_functions/common/dequantization_operations.hpp" + +namespace LayerTestsDefinitions { + +class ConvolutionBackpropDataTransformationParam { +public: + ngraph::builder::subgraph::FakeQuantizeOnData fakeQuantizeOnData; + ngraph::builder::subgraph::FakeQuantizeOnWeights fakeQuantizeOnWeights; + ngraph::builder::subgraph::DequantizationOperations dequantizationOnWeights; + std::string layerName; + std::string expectedKernelType; + + ConvolutionBackpropDataTransformationParam() = default; + ConvolutionBackpropDataTransformationParam( + const ngraph::builder::subgraph::FakeQuantizeOnData& fakeQuantizeOnData, + const ngraph::builder::subgraph::FakeQuantizeOnWeights& fakeQuantizeOnWeights, + std::string layerName, + std::string expectedKernelType) : + fakeQuantizeOnData(fakeQuantizeOnData), fakeQuantizeOnWeights(fakeQuantizeOnWeights), + layerName(std::move(layerName)), expectedKernelType(std::move(expectedKernelType)) {} + ConvolutionBackpropDataTransformationParam( + const ngraph::builder::subgraph::FakeQuantizeOnData& fakeQuantizeOnData, + ngraph::builder::subgraph::DequantizationOperations dequantizationOnWeights, + std::string layerName, + std::string expectedKernelType) : + fakeQuantizeOnData(fakeQuantizeOnData), dequantizationOnWeights(std::move(dequantizationOnWeights)), + layerName(std::move(layerName)), expectedKernelType(std::move(expectedKernelType)) {} +}; + +typedef std::tuple< + ngraph::element::Type, // netPrecision + ngraph::Shape, // inputShape + ngraph::Shape, // outputShape + std::string, // targetDevice + ngraph::pass::low_precision::LayerTransformation::Params, + ConvolutionBackpropDataTransformationParam +> ConvolutionBackpropDataTransformationParams; + +class ConvolutionBackpropDataTransformation : + public testing::WithParamInterface, + public LayerTestsUtils::LayerTransformation { +public: + static std::string getTestCaseName(testing::TestParamInfo obj); + +protected: + void SetUp() override; + + void Run() override; +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/convolution_backprop_data_transformation.cpp b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/convolution_backprop_data_transformation.cpp new file mode 100644 index 00000000000..951af4fdd4e --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/src/low_precision_transformations/convolution_backprop_data_transformation.cpp @@ -0,0 +1,77 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "low_precision_transformations/convolution_backprop_data_transformation.hpp" + +#include +#include +#include + +#include "lpt_ngraph_functions/convolution_backprop_data_function.hpp" + +namespace LayerTestsDefinitions { + +std::string ConvolutionBackpropDataTransformation::getTestCaseName(testing::TestParamInfo obj) { + ngraph::element::Type netPrecision; + ngraph::Shape inputShape; + ngraph::Shape outputShape; + std::string targetDevice; + ngraph::pass::low_precision::LayerTransformation::Params params; + ConvolutionBackpropDataTransformationParam param; + std::tie(netPrecision, inputShape, outputShape, targetDevice, params, param) = obj.param; + + std::ostringstream result; + result << getTestCaseNameByParams(netPrecision, inputShape, targetDevice, params) << "_" << + outputShape << "_" << + param.fakeQuantizeOnData << "_" << + param.fakeQuantizeOnWeights << "_" << + param.dequantizationOnWeights; + return result.str(); +} + +void ConvolutionBackpropDataTransformation::SetUp() { + threshold = 0.1f; + + ngraph::element::Type netPrecision; + ngraph::Shape inputShape; + ngraph::Shape outputShape; + ngraph::pass::low_precision::LayerTransformation::Params params; + ConvolutionBackpropDataTransformationParam param; + std::tie(netPrecision, inputShape, outputShape, targetDevice, params, param) = this->GetParam(); + + std::shared_ptr weights; + + if (!param.fakeQuantizeOnWeights.empty()) { + weights = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getWeights( + ngraph::Shape{inputShape[1], inputShape[1] / 2, 1, 1}, + netPrecision, + param.fakeQuantizeOnWeights); + } else { + weights = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::getWeights( + ngraph::Shape{inputShape[1], inputShape[1] / 2, 1, 1}, + netPrecision, + param.dequantizationOnWeights); + } + + function = ngraph::builder::subgraph::ConvolutionBackpropDataFunction::get( + netPrecision, + inputShape, + outputShape, + param.fakeQuantizeOnData, + weights); +} + +void ConvolutionBackpropDataTransformation::Run() { + LayerTestsCommon::Run(); + + const auto params = std::get<5>(GetParam()); + const auto actualType = getRuntimePrecision(params.layerName); + EXPECT_EQ(actualType, params.expectedKernelType); +} + +TEST_P(ConvolutionBackpropDataTransformation, CompareWithRefImpl) { + Run(); +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/convolution_backprop_data_function.hpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/convolution_backprop_data_function.hpp new file mode 100644 index 00000000000..fa05d7b3cb1 --- /dev/null +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/convolution_backprop_data_function.hpp @@ -0,0 +1,54 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include "lpt_ngraph_functions/common/fake_quantize_on_weights.hpp" +#include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp" +#include "lpt_ngraph_functions/common/dequantization_operations.hpp" + +namespace ngraph { +namespace builder { +namespace subgraph { + +class ConvolutionBackpropDataFunction { +public: + static std::shared_ptr getWeights( + const Shape& shape, + const element::Type& netPrecision, + const builder::subgraph::DequantizationOperations& dequantizationOnWeights, + const std::shared_ptr& value = nullptr); + static std::shared_ptr getWeights( + const Shape& shape, + const element::Type& netPrecision, + const builder::subgraph::FakeQuantizeOnWeights& fqOnWeights, + const std::shared_ptr& value = nullptr); + static std::shared_ptr get( + const element::Type netPrecision, + const Shape& inputShape, + const Shape& outputShape, + const builder::subgraph::FakeQuantizeOnData& fqOnData, + const std::shared_ptr& weights); + static std::shared_ptr getOriginal( + const element::Type precision, + const element::Type netPrecision, + const Shape& inputShape, + const Shape& outputShape, + const builder::subgraph::DequantizationOperations& dequantization, + const std::shared_ptr& weights); + static std::shared_ptr getReference( + const element::Type precision, + const element::Type netPrecision, + const Shape& inputShape, + const Shape& outputShape, + const builder::subgraph::DequantizationOperations& dequantization, + const std::shared_ptr& weights, + const builder::subgraph::DequantizationOperations& dequantizationAfter); +}; +} // namespace subgraph +} // namespace builder +} // namespace ngraph diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_backprop_data_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_backprop_data_function.cpp new file mode 100644 index 00000000000..ae7d3847f69 --- /dev/null +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_backprop_data_function.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "lpt_ngraph_functions/convolution_backprop_data_function.hpp" + +#include +#include +#include "ngraph_functions/subgraph_builders.hpp" +#include "low_precision/network_helper.hpp" + +#include "lpt_ngraph_functions/common/fake_quantize_on_weights.hpp" +#include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp" +#include "lpt_ngraph_functions/common/dequantization_operations.hpp" +#include "lpt_ngraph_functions/common/builders.hpp" +#include "low_precision/common/dequantization_op.hpp" +#include "low_precision/network_helper.hpp" + +using namespace ngraph::pass::low_precision; + +namespace ngraph { +namespace builder { +namespace subgraph { + +std::shared_ptr ConvolutionBackpropDataFunction::get( + const element::Type netPrecision, + const Shape& inputShape, + const Shape& outputShape, + const builder::subgraph::FakeQuantizeOnData& fqOnData, + const std::shared_ptr& weights) { + const auto input = std::make_shared(netPrecision, inputShape); + const auto fq = makeFakeQuantize(input, netPrecision, fqOnData); + + auto convolutionBackpropData = std::make_shared( + fq, + weights, + Strides{ 1, 1 }, + CoordinateDiff{ 0, 0 }, + CoordinateDiff{ 0, 0 }, + Strides{ 1, 1 }); + + ngraph::ResultVector results{ std::make_shared(convolutionBackpropData) }; + return std::make_shared(results, ParameterVector{ input }, "ConvolutionBackpropDataTransformation"); +} + +std::shared_ptr ConvolutionBackpropDataFunction::getWeights( + const Shape& shape, + const element::Type& netPrecision, + const builder::subgraph::FakeQuantizeOnWeights& fqOnWeights, + const std::shared_ptr& value) { + const auto weights = value != nullptr ? + value : + std::make_shared( + element::i8, + shape, + std::vector(shape_size(shape), 1)); + const auto convert = std::make_shared(weights, netPrecision); + OutputVector convertedOutput(1); + convert->constant_fold(convertedOutput, convert->input_values()); + const auto convertedWeights = convertedOutput[0].get_node_shared_ptr(); + const auto fq = makeFakeQuantize(convertedWeights, netPrecision, fqOnWeights); + + return fq; +} + +std::shared_ptr ConvolutionBackpropDataFunction::getWeights( + const Shape& shape, + const element::Type& netPrecision, + const builder::subgraph::DequantizationOperations& dequantizationOnWeights, + const std::shared_ptr& value) { + auto weights = + value != nullptr ? + value : + std::make_shared( + element::i8, + shape, + std::vector(shape_size(shape), 1)); + auto dequantizationStructure = dequantizationOnWeights; + dequantizationStructure.setPrecision(netPrecision); + if (!dequantizationOnWeights.subtract.constantPrecision.is_real()) { + dequantizationStructure.subtract.constantPrecision = dequantizationOnWeights.subtract.constantPrecision; + } + if (weights->get_element_type().is_real()) { + weights = as_type_ptr(fold(weights, netPrecision)); + } + const auto dq = makeDequantization(weights, dequantizationStructure); + + return dq; +} + +std::shared_ptr ConvolutionBackpropDataFunction::getOriginal( + const element::Type precision, + const element::Type netPrecision, + const Shape& inputShape, + const Shape& outputShape, + const builder::subgraph::DequantizationOperations& dequantization, + const std::shared_ptr& weights) { + const auto input = std::make_shared(precision, inputShape); + auto dequantizationStructure = dequantization; + dequantizationStructure.multiply.outPrecision = netPrecision; + const auto activations = makeDequantization(input, dequantizationStructure); + + auto convolutionBackpropData = std::make_shared( + activations, + weights, + Strides{ 1, 1 }, + CoordinateDiff{ 0, 0 }, + CoordinateDiff{ 0, 0 }, + Strides{ 1, 1 }); + + convolutionBackpropData->set_friendly_name("output"); + ngraph::ResultVector results{ std::make_shared(convolutionBackpropData) }; + return std::make_shared(results, ParameterVector{ input }, "ConvolutionBackpropDataTransformation"); +} + +std::shared_ptr ConvolutionBackpropDataFunction::getReference( + const element::Type precision, + const element::Type netPrecision, + const Shape& inputShape, + const Shape& outputShape, + const builder::subgraph::DequantizationOperations& dequantization, + const std::shared_ptr& weights, + const builder::subgraph::DequantizationOperations& dequantizationAfter) { + const auto input = std::make_shared(precision, inputShape); + auto dequantizationStructure = dequantization; + dequantizationStructure.multiply.outPrecision = netPrecision; + const auto activations = makeDequantization(input, dequantizationStructure); + + auto convolutionBackpropData = std::make_shared>( + std::vector{ element::f32, element::f32 }, + std::vector{ dequantizationAfter.empty() ? netPrecision : element::f32 }, + ngraph::op::TemporaryReplaceOutputType(activations, element::f32).get(), + ngraph::op::TemporaryReplaceOutputType(weights, element::f32).get(), + Strides{ 1, 1 }, + CoordinateDiff{ 0, 0 }, + CoordinateDiff{ 0, 0 }, + Strides{ 1, 1 }); + + auto dequantizationStructureAfter = dequantizationAfter; + dequantizationStructureAfter.multiply.outPrecision = netPrecision; + const auto result = makeDequantization(convolutionBackpropData, dequantizationStructureAfter); + result->set_friendly_name("output"); + ngraph::ResultVector results{ std::make_shared(result) }; + return std::make_shared(results, ParameterVector{ input }, "ConvolutionBackpropDataTransformation"); +} + +} // namespace subgraph +} // namespace builder +} // namespace ngraph diff --git a/ngraph/core/include/ngraph/op/convolution.hpp b/ngraph/core/include/ngraph/op/convolution.hpp index c6516a5572a..72a365be533 100644 --- a/ngraph/core/include/ngraph/op/convolution.hpp +++ b/ngraph/core/include/ngraph/op/convolution.hpp @@ -86,8 +86,8 @@ namespace ngraph class NGRAPH_API ConvolutionBackpropData : public Op { public: - static constexpr NodeTypeInfo type_info{"ConvolutionBackpropData", 1}; - const NodeTypeInfo& get_type_info() const override { return type_info; } + NGRAPH_RTTI_DECLARATION; + /// \brief Constructs a batched-convolution data batch-backprop operation. ConvolutionBackpropData() = default; // clang-format off diff --git a/ngraph/core/include/ngraph/op/group_conv.hpp b/ngraph/core/include/ngraph/op/group_conv.hpp index 3c175b51297..ebda0392d96 100644 --- a/ngraph/core/include/ngraph/op/group_conv.hpp +++ b/ngraph/core/include/ngraph/op/group_conv.hpp @@ -85,8 +85,8 @@ namespace ngraph class NGRAPH_API GroupConvolutionBackpropData : public Op { public: - static constexpr NodeTypeInfo type_info{"GroupConvolutionBackpropData", 1}; - const NodeTypeInfo& get_type_info() const override { return type_info; } + NGRAPH_RTTI_DECLARATION; + /// \brief Constructs a batched-convolution data batch-backprop operation. GroupConvolutionBackpropData(); // clang-format off diff --git a/ngraph/core/src/op/convolution.cpp b/ngraph/core/src/op/convolution.cpp index 667fa933046..6be59d5132e 100644 --- a/ngraph/core/src/op/convolution.cpp +++ b/ngraph/core/src/op/convolution.cpp @@ -102,12 +102,14 @@ shared_ptr op::v1::Convolution::clone_with_new_inputs(const OutputVector& m_auto_pad); } -constexpr NodeTypeInfo op::v1::ConvolutionBackpropData::type_info; shared_ptr op::v1::Convolution::get_default_value() const { return ngraph::make_constant_from_string("0", get_element_type(), get_shape()); } +// *** ConvolutionBackpropData OP SET 1 *** +NGRAPH_RTTI_DEFINITION(op::v1::ConvolutionBackpropData, "ConvolutionBackpropData", 1); + op::v1::ConvolutionBackpropData::ConvolutionBackpropData(const Output& data, const Output& filters, const Output& output_shape, diff --git a/ngraph/core/src/op/group_conv.cpp b/ngraph/core/src/op/group_conv.cpp index 4efbcae117e..b9d7cc4be10 100644 --- a/ngraph/core/src/op/group_conv.cpp +++ b/ngraph/core/src/op/group_conv.cpp @@ -286,7 +286,7 @@ shared_ptr op::v1::GroupConvolution::clone_with_new_inputs(const OutputVec // v1::GroupConvolutionBackpropData //------------------------------------------------------------------------------ -constexpr NodeTypeInfo op::v1::GroupConvolutionBackpropData::type_info; +NGRAPH_RTTI_DEFINITION(op::v1::GroupConvolutionBackpropData, "GroupConvolutionBackpropData", 1); op::v1::GroupConvolutionBackpropData::GroupConvolutionBackpropData() : Op()
Operation