From 3b88682159c5af5522365918703c9e7407f4b730 Mon Sep 17 00:00:00 2001 From: Vitaliy Urusovskij Date: Tue, 23 Nov 2021 09:27:37 +0300 Subject: [PATCH] Support NonConst pads_begin and pads_end in Pad op (#8697) * Support pads_begin & pads_end as dynamic ops in Pad * Extend Pad template test w/ NonConst PB & PE cases * Remove xfails for 69443 after issue was fixed --- .../tests/functional/op_reference/pad.cpp | 67 +++++++++++++++++++ ngraph/core/src/op/pad.cpp | 21 +++++- runtime/bindings/python/tests/__init__.py | 1 - .../python/tests/test_onnx/test_backend.py | 7 -- .../python/tests_compatibility/__init__.py | 1 - .../test_onnx/test_backend.py | 7 -- 6 files changed, 86 insertions(+), 18 deletions(-) diff --git a/docs/template_plugin/tests/functional/op_reference/pad.cpp b/docs/template_plugin/tests/functional/op_reference/pad.cpp index dfe16f69ad6..df8a4155977 100644 --- a/docs/template_plugin/tests/functional/op_reference/pad.cpp +++ b/docs/template_plugin/tests/functional/op_reference/pad.cpp @@ -116,6 +116,64 @@ TEST_P(ReferencePadTestParamsOk, CompareWithRefs) { EXPECT_NO_THROW(Exec()); } +class ReferencePadTestNonConstPadsBeginPadsEnd : public ReferencePadTest { +public: + void SetUp() override { + SKIP_IF_CURRENT_TEST_IS_DISABLED(); + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.inputData.data, params.padsBegin.data, params.padsEnd.data}; + refOutData = {params.expectedOutput.data}; + } + +private: + static std::shared_ptr CreateFunction(const PadParams& params) { + const auto data = std::make_shared(params.inputData.type, + params.inputData.shape); + const auto padsBegin = std::make_shared(params.padsBegin.type, + params.padsBegin.shape); + const auto padsEnd = std::make_shared(params.padsEnd.type, + params.padsEnd.shape); + const auto f = [&] { + if (params.useConstValue) { + // pad_value should be used only in CONSTANT mode + const auto padVal = op::v0::Constant::create(params.constantValue.type, + params.constantValue.shape, + params.constantValue.data.data()); + return std::make_shared(std::make_shared(data, + padsBegin, + padsEnd, + padVal, + params.padMode), + ParameterVector{data, padsBegin, padsEnd}); + } + + return std::make_shared(std::make_shared(data, + padsBegin, + padsEnd, + params.padMode), + ParameterVector{data, padsBegin, padsEnd}); + }(); + return f; + } +}; + +TEST_P(ReferencePadTestNonConstPadsBeginPadsEnd, CompareWithRefs) { + Exec(); +} + +class ReferencePadTestNonConstPadsBeginPadsEndTooLarge : public ReferencePadTestNonConstPadsBeginPadsEnd {}; + +TEST_P(ReferencePadTestNonConstPadsBeginPadsEndTooLarge, CompareWithRefs) { + EXPECT_ANY_THROW(Exec()); +} + +class ReferencePadTestNonConstPadsBeginPadsEndParamsOk : public ReferencePadTestNonConstPadsBeginPadsEnd {}; + +TEST_P(ReferencePadTestNonConstPadsBeginPadsEndParamsOk, CompareWithRefs) { + EXPECT_NO_THROW(Exec()); +} + template std::vector generateParams() { using T = typename element_type_traits::value_type; @@ -1005,6 +1063,9 @@ std::vector generateCombinedParams() { INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTest, testing::ValuesIn(generateCombinedParams()), ReferencePadTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTestNonConstPadsBeginPadsEnd, + testing::ValuesIn(generateCombinedParams()), ReferencePadTest::getTestCaseName); + template std::vector generateParamsTooLarge() { using T = typename element_type_traits::value_type; @@ -1052,6 +1113,9 @@ std::vector generateCombinedParamsTooLarge() { INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTestParamsTooLarge, testing::ValuesIn(generateCombinedParamsTooLarge()), ReferencePadTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTestNonConstPadsBeginPadsEndTooLarge, + testing::ValuesIn(generateCombinedParamsTooLarge()), ReferencePadTest::getTestCaseName); + template std::vector generateParamsOk() { using T = typename element_type_traits::value_type; @@ -1098,4 +1162,7 @@ std::vector generateCombinedParamsOk() { INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTestParamsOk, testing::ValuesIn(generateCombinedParamsOk()), ReferencePadTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTestNonConstPadsBeginPadsEndParamsOk, + testing::ValuesIn(generateCombinedParamsOk()), ReferencePadTest::getTestCaseName); } // namespace \ No newline at end of file diff --git a/ngraph/core/src/op/pad.cpp b/ngraph/core/src/op/pad.cpp index a033f74587e..87d43449e2f 100644 --- a/ngraph/core/src/op/pad.cpp +++ b/ngraph/core/src/op/pad.cpp @@ -200,7 +200,24 @@ bool op::v1::Pad::evaluate_pad(const HostTensorVector& outputs, const HostTensor } else { pad_value = pad_zero_value.data(); } + + // compute pads_begin and pads_end CoordinateDiffs from pads_begin + // and pads_end shapes and reshape output to determine shape + // (in case pads_begin and pads_end are Parameters, output is dynamic with static rank). + + op::v0::Constant pads_begin_const(inputs[1]); + CoordinateDiff pads_begin_coord(pads_begin_const.cast_vector()); + op::v0::Constant pads_end_const(inputs[2]); + CoordinateDiff pads_end_coord(pads_end_const.cast_vector()); + + auto data_shape = data->get_shape(); + ov::Shape padded_shape(data_shape.size()); + for (size_t i = 0; i < data_shape.size(); ++i) { + padded_shape[i] = data_shape[i] + pads_begin_coord[i] + pads_end_coord[i]; + } + const auto& out = outputs[0]; + out->set_shape(padded_shape); ngraph::runtime::reference::pad(data->get_data_ptr(), pad_value, @@ -208,8 +225,8 @@ bool op::v1::Pad::evaluate_pad(const HostTensorVector& outputs, const HostTensor elem_size, data->get_shape(), out->get_shape(), - get_pads_begin(), - get_pads_end(), + pads_begin_coord, + pads_end_coord, get_pad_mode()); return true; diff --git a/runtime/bindings/python/tests/__init__.py b/runtime/bindings/python/tests/__init__.py index 48c46843e7e..7adc0ee60c0 100644 --- a/runtime/bindings/python/tests/__init__.py +++ b/runtime/bindings/python/tests/__init__.py @@ -26,7 +26,6 @@ skip_segfault = pytest.mark.skip(reason="Segmentation fault error") xfail_accuracy = xfail_test(reason="Accuracy") xfail_issue_FLOAT_LIKE = xfail_test(reason="Use of bfloat16 or float16") xfail_issue_69444 = xfail_test(reason="failed with accuracy issue") -xfail_issue_69443 = xfail_test(reason="Error in ref. implementation due to the empty pads_begin, pads_end") skip_issue_67415 = pytest.mark.skip(reason="RuntimeError: Unsupported data type for when filling blob!") xfail_issue_67415 = xfail_test(reason="RuntimeError: Unsupported data type for when filling blob!") xfail_issue_33488 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations: " diff --git a/runtime/bindings/python/tests/test_onnx/test_backend.py b/runtime/bindings/python/tests/test_onnx/test_backend.py index 962ee68537a..51a95bb416f 100644 --- a/runtime/bindings/python/tests/test_onnx/test_backend.py +++ b/runtime/bindings/python/tests/test_onnx/test_backend.py @@ -48,7 +48,6 @@ from tests import ( xfail_issue_63136, xfail_issue_63137, xfail_issue_63138, - xfail_issue_69443, xfail_issue_69444, ) from tests.test_onnx.utils.onnx_backend import OpenVinoTestBackend @@ -126,12 +125,6 @@ tests_expected_to_fail = [ "OnnxBackendNodeModelTest.test_lstm_with_initial_bias_cpu", "OnnxBackendNodeModelTest.test_lstm_with_peepholes_cpu", ), - ( - xfail_issue_69443, - "OnnxBackendNodeModelTest.test_constant_pad_cpu", - "OnnxBackendNodeModelTest.test_edge_pad_cpu", - "OnnxBackendNodeModelTest.test_reflect_pad_cpu", - ), ( xfail_issue_39658, "OnnxBackendNodeModelTest.test_tile_cpu", diff --git a/runtime/bindings/python/tests_compatibility/__init__.py b/runtime/bindings/python/tests_compatibility/__init__.py index 714761dc1f6..c3bd3d2cfd4 100644 --- a/runtime/bindings/python/tests_compatibility/__init__.py +++ b/runtime/bindings/python/tests_compatibility/__init__.py @@ -25,7 +25,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): skip_segfault = pytest.mark.skip(reason="Segmentation fault error") xfail_accuracy = xfail_test(reason="Accuracy") xfail_issue_69444 = xfail_test(reason="failed with accuracy issue") -xfail_issue_69443 = xfail_test(reason="Segmentation fault due to empty pads_begin, pads_end") xfail_issue_67415 = xfail_test(reason="RuntimeError: Unsupported data type for when filling blob!") xfail_issue_33488 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations: " "MaxUnpool") diff --git a/runtime/bindings/python/tests_compatibility/test_onnx/test_backend.py b/runtime/bindings/python/tests_compatibility/test_onnx/test_backend.py index d052bb530c1..bd4d8284b2c 100644 --- a/runtime/bindings/python/tests_compatibility/test_onnx/test_backend.py +++ b/runtime/bindings/python/tests_compatibility/test_onnx/test_backend.py @@ -47,7 +47,6 @@ from tests_compatibility import ( xfail_issue_63136, xfail_issue_63137, xfail_issue_63138, - xfail_issue_69443, xfail_issue_69444, ) from tests_compatibility.test_onnx.utils.onnx_backend import OpenVinoTestBackend @@ -111,12 +110,6 @@ tests_expected_to_fail = [ "OnnxBackendNodeModelTest.test_lstm_with_initial_bias_cpu", "OnnxBackendNodeModelTest.test_lstm_with_peepholes_cpu", ), - ( - xfail_issue_69443, - "OnnxBackendNodeModelTest.test_constant_pad_cpu", - "OnnxBackendNodeModelTest.test_edge_pad_cpu", - "OnnxBackendNodeModelTest.test_reflect_pad_cpu", - ), ( xfail_issue_39658, "OnnxBackendNodeModelTest.test_tile_cpu",