diff --git a/src/common/transformations/include/transformations/op_conversions/gather_normalize_negative_indices.hpp b/src/common/transformations/include/transformations/op_conversions/gather_normalize_negative_indices.hpp deleted file mode 100644 index bb912f5a980..00000000000 --- a/src/common/transformations/include/transformations/op_conversions/gather_normalize_negative_indices.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2018-2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include "openvino/pass/graph_rewrite.hpp" -#include "transformations_visibility.hpp" - -namespace ov { -namespace pass { - -class TRANSFORMATIONS_API GatherNegativeConstIndicesNormalize; - -} // namespace pass -} // namespace ov - -/** - * @ingroup ie_transformation_common_api - * @brief GatherNegativeConstIndicesNormalize checks if indices value is negative scalar and - * normalizes it using ShapeOf->Add->Cast subgraph. - * We need to remove this transformation after adding support of negative indices in - * future version of Gather operation. - */ -class ov::pass::GatherNegativeConstIndicesNormalize : public ov::pass::MatcherPass { -public: - OPENVINO_RTTI("GatherNegativeConstIndicesNormalize", "0"); - GatherNegativeConstIndicesNormalize(); -}; diff --git a/src/common/transformations/src/transformations/common_optimizations/common_optimizations.cpp b/src/common/transformations/src/transformations/common_optimizations/common_optimizations.cpp index 8ad09f95ded..4d4cebe5c62 100644 --- a/src/common/transformations/src/transformations/common_optimizations/common_optimizations.cpp +++ b/src/common/transformations/src/transformations/common_optimizations/common_optimizations.cpp @@ -97,7 +97,6 @@ #include "transformations/op_conversions/detection_output_upgrade.hpp" #include "transformations/op_conversions/einsum_decomposition.hpp" #include "transformations/op_conversions/eye_decomposition.hpp" -#include "transformations/op_conversions/gather_normalize_negative_indices.hpp" #include "transformations/op_conversions/gelu7_downgrade.hpp" #include "transformations/op_conversions/group_normalization_decomposition.hpp" #include "transformations/op_conversions/hsigmoid_decomposition.hpp" @@ -170,7 +169,6 @@ bool ov::pass::CommonOptimizations::run_on_model(const std::shared_ptradd_matcher(); ADD_MATCHER(decomp, SoftSignDecomposition) - ADD_MATCHER(decomp, GatherNegativeConstIndicesNormalize) ADD_MATCHER(decomp, DropoutWithRandomUniformReplacer) ADD_MATCHER(decomp, TransposeReshapeEliminationForMatmul) ADD_MATCHER(decomp, EyeDecomposition) diff --git a/src/common/transformations/src/transformations/op_conversions/convert_gather_downgrade.cpp b/src/common/transformations/src/transformations/op_conversions/convert_gather_downgrade.cpp index ae0aeb4d99a..4c525f7d3dd 100644 --- a/src/common/transformations/src/transformations/op_conversions/convert_gather_downgrade.cpp +++ b/src/common/transformations/src/transformations/op_conversions/convert_gather_downgrade.cpp @@ -48,8 +48,59 @@ pass::ConvertGather8ToGather7::ConvertGather8ToGather7() { if (!gather_v8_node) return false; + auto data = gather_v8_node->input_value(0); + auto indices_constant = + std::dynamic_pointer_cast(gather_v8_node->input_value(1).get_node_shared_ptr()); + auto axis_constant = + std::dynamic_pointer_cast(gather_v8_node->input_value(2).get_node_shared_ptr()); + if (!indices_constant || !axis_constant) + return false; + + auto axis = axis_constant->cast_vector(); + if (axis.size() != 1) { + return false; + } + auto axis_value = axis[0]; + // normalize `axis` value if it is negative + if (axis_value < 0) { + if (!data.get_partial_shape().rank().is_static()) { + return false; + } + axis_value = axis_value + data.get_partial_shape().rank().get_length(); + } + if (data.get_partial_shape().rank().get_length() < axis_value) { + return false; + } + // check `axis` dimension of data tensor is static + if (!data.get_partial_shape()[axis_value].is_static()) { + return false; + } + auto axis_dim = data.get_partial_shape()[axis_value].get_length(); + + auto indices = indices_constant->cast_vector(); + // Check all the indices are not out of bound and check whether normalization is possible for negative values + bool do_indices_normalization = false; + for (size_t i = 0; i < indices.size(); i++) { + if (indices[i] < -axis_dim || indices[i] >= axis_dim) { + return false; + } + if (indices[i] < 0) { + do_indices_normalization = true; + indices[i] = indices[i] + axis_dim; + } + } + + std::shared_ptr new_indices_constant; + if (do_indices_normalization) { + new_indices_constant = std::make_shared(indices_constant->get_element_type(), + indices_constant->get_shape(), + indices); + } else { + new_indices_constant = indices_constant; + } + auto gather_v7_node = make_shared(gather_v8_node->input_value(0), - gather_v8_node->input_value(1), + new_indices_constant, gather_v8_node->input_value(2), gather_v8_node->get_batch_dims()); diff --git a/src/common/transformations/src/transformations/op_conversions/gather_normalize_negative_indices.cpp b/src/common/transformations/src/transformations/op_conversions/gather_normalize_negative_indices.cpp deleted file mode 100644 index 47ff221d82f..00000000000 --- a/src/common/transformations/src/transformations/op_conversions/gather_normalize_negative_indices.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (C) 2018-2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "transformations/op_conversions/gather_normalize_negative_indices.hpp" - -#include - -#include "itt.hpp" -#include "openvino/core/rt_info.hpp" -#include "openvino/core/validation_util.hpp" -#include "openvino/op/add.hpp" -#include "openvino/op/constant.hpp" -#include "openvino/op/gather.hpp" -#include "openvino/op/shape_of.hpp" -#include "openvino/pass/pattern/op/wrap_type.hpp" - -ov::pass::GatherNegativeConstIndicesNormalize::GatherNegativeConstIndicesNormalize() { - MATCHER_SCOPE(GatherNegativeConstIndicesNormalize); - auto data_input = pattern::any_input(pattern::has_static_rank()); - auto axis_input = ov::pass::pattern::wrap_type(); - auto indices_input = ov::pass::pattern::wrap_type(); - auto gather_node = ov::pass::pattern::wrap_type({data_input, indices_input, axis_input}); - - matcher_pass_callback callback = [=](ov::pass::pattern::Matcher& m) { - auto& pattern_to_output = m.get_pattern_value_map(); - auto gather = pattern_to_output.at(gather_node).get_node_shared_ptr(); - auto data = pattern_to_output.at(data_input); - auto axis_constant = - std::dynamic_pointer_cast(pattern_to_output.at(axis_input).get_node_shared_ptr()); - auto indices_constant = - std::dynamic_pointer_cast(pattern_to_output.at(indices_input).get_node_shared_ptr()); - - if (!gather || !axis_constant || !indices_constant) { - return false; - } - - auto indices = indices_constant->cast_vector(); - if (indices.size() != 1 || indices[0] >= 0) { - return false; - } - - auto axis = axis_constant->cast_vector(); - if (axis.size() != 1) { - return false; - } - - auto axis_value = axis[0]; - - // normalize `axis` value if it is negative - if (axis_value < 0) { - axis_value = axis_value + data.get_partial_shape().rank().get_length(); - } - - if (data.get_partial_shape().rank().get_length() < axis_value) { - return false; - } - - // check `axis` dimension of data tensor is static - if (!data.get_partial_shape()[axis_value].is_static()) { - return false; - } - - auto input_type = indices_constant->get_element_type(); - auto shape_of = std::make_shared(data, input_type); - auto input_gather = - std::make_shared(shape_of, - ov::op::v0::Constant::create(input_type, Shape{}, {axis_value}), - ov::op::v0::Constant::create(input_type, Shape{}, {0})); - - std::shared_ptr add = std::make_shared(input_gather, indices_constant); - OPENVINO_SUPPRESS_DEPRECATED_START - if (auto folded_const = ov::get_constant_from_source(add)) { - OPENVINO_SUPPRESS_DEPRECATED_END - add = folded_const; - } - gather->input(1).replace_source_output(add); - - ov::copy_runtime_info(gather, {shape_of, input_gather, add}); - - return true; - }; - - auto m = std::make_shared(gather_node, matcher_name); - register_matcher(m, callback); -} diff --git a/src/common/transformations/tests/op_conversions/convert_gather_downgrade_test.cpp b/src/common/transformations/tests/op_conversions/convert_gather_downgrade_test.cpp index 9f8447b9c77..b38ff9239c5 100644 --- a/src/common/transformations/tests/op_conversions/convert_gather_downgrade_test.cpp +++ b/src/common/transformations/tests/op_conversions/convert_gather_downgrade_test.cpp @@ -55,7 +55,7 @@ TEST_F(TransformationTestsF, ConvertGather7toGather1_nonzero_batch_dims) { } } -TEST_F(TransformationTestsF, ConvertGather8toGather7) { +TEST_F(TransformationTestsF, ConvertGather8toGather7_param_indices) { { auto data = std::make_shared(element::f32, Shape{2, 3}); auto indices = std::make_shared(element::i32, Shape{2, 2}); @@ -68,15 +68,98 @@ TEST_F(TransformationTestsF, ConvertGather8toGather7) { manager.register_pass(); } +} + +TEST_F(TransformationTestsF, ConvertGather8toGather7_const_indices) { + { + auto data = std::make_shared(element::f32, Shape{2, 3}); + auto indices = opset8::Constant::create(element::i32, Shape{2, 2}, {0, 1, 2, 0}); + auto axis = opset1::Constant::create(element::i32, Shape{1}, {1}); + int64_t batch_dims = 1; + + auto gather_v8 = std::make_shared(data, indices, axis, batch_dims); + + model = std::make_shared(NodeVector{gather_v8}, ParameterVector{data}); + + manager.register_pass(); + } { auto data = std::make_shared(element::f32, Shape{2, 3}); - auto indices = std::make_shared(element::i32, Shape{2, 2}); + auto indices = opset8::Constant::create(element::i32, Shape{2, 2}, {0, 1, 2, 0}); auto axis = opset1::Constant::create(element::i32, Shape{1}, {1}); int64_t batch_dims = 1; auto gather_v7 = std::make_shared(data, indices, axis, batch_dims); - model_ref = std::make_shared(NodeVector{gather_v7}, ParameterVector{data, indices}); + model_ref = std::make_shared(NodeVector{gather_v7}, ParameterVector{data}); + } +} + +TEST_F(TransformationTestsF, ConvertGather8toGather7_negative_indices) { + { + auto data = std::make_shared(element::f32, Shape{2, 3}); + auto indices = opset8::Constant::create(element::i32, Shape{2, 2}, {2, 1, 0, -1}); + auto axis = opset1::Constant::create(element::i32, Shape{1}, {1}); + int64_t batch_dims = 1; + + auto gather_v8 = std::make_shared(data, indices, axis, batch_dims); + + model = std::make_shared(NodeVector{gather_v8}, ParameterVector{data}); + + manager.register_pass(); + comparator.enable(FunctionsComparator::CONST_VALUES); + } + + { + auto data = std::make_shared(element::f32, Shape{2, 3}); + auto indices = opset8::Constant::create(element::i32, Shape{2, 2}, {2, 1, 0, 2}); + auto axis = opset1::Constant::create(element::i32, Shape{1}, {1}); + int64_t batch_dims = 1; + + auto gather_v7 = std::make_shared(data, indices, axis, batch_dims); + + model_ref = std::make_shared(NodeVector{gather_v7}, ParameterVector{data}); + } +} + +TEST_F(TransformationTestsF, ConvertGather8toGather7_out_of_bound_indices) { + { + auto data = std::make_shared(element::f32, Shape{2, 3}); + auto indices = opset8::Constant::create(element::i32, Shape{2, 2}, {0, 1, 2, 3}); + auto axis = opset1::Constant::create(element::i32, Shape{1}, {1}); + int64_t batch_dims = 1; + + auto gather_v8 = std::make_shared(data, indices, axis, batch_dims); + + model = std::make_shared(NodeVector{gather_v8}, ParameterVector{data}); + + manager.register_pass(); + } +} + +TEST_F(TransformationTestsF, ConvertGather8toGather7_negative_axis) { + { + auto data = std::make_shared(element::f32, Shape{2, 3}); + auto indices = opset8::Constant::create(element::i32, Shape{2, 2}, {0, 1, 2, 0}); + auto axis = opset1::Constant::create(element::i32, Shape{1}, {-1}); + int64_t batch_dims = 1; + + auto gather_v8 = std::make_shared(data, indices, axis, batch_dims); + + model = std::make_shared(NodeVector{gather_v8}, ParameterVector{data}); + + manager.register_pass(); + } + + { + auto data = std::make_shared(element::f32, Shape{2, 3}); + auto indices = opset8::Constant::create(element::i32, Shape{2, 2}, {0, 1, 2, 0}); + auto axis = opset1::Constant::create(element::i32, Shape{1}, {-1}); + int64_t batch_dims = 1; + + auto gather_v7 = std::make_shared(data, indices, axis, batch_dims); + + model_ref = std::make_shared(NodeVector{gather_v7}, ParameterVector{data}); } } diff --git a/src/common/transformations/tests/op_conversions/gather_normalize_negative_indices_test.cpp b/src/common/transformations/tests/op_conversions/gather_normalize_negative_indices_test.cpp deleted file mode 100644 index 8f71da2a336..00000000000 --- a/src/common/transformations/tests/op_conversions/gather_normalize_negative_indices_test.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (C) 2018-2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "transformations/op_conversions/gather_normalize_negative_indices.hpp" - -#include - -#include -#include - -#include "common_test_utils/ov_test_utils.hpp" -#include "openvino/core/model.hpp" -#include "openvino/core/validation_util.hpp" -#include "openvino/opsets/opset7.hpp" -#include "openvino/pass/manager.hpp" -#include "transformations/init_node_info.hpp" -using namespace ov; -using namespace testing; - -TEST_F(TransformationTestsF, GatherNegativeIndicesNormalize) { - { - auto data = std::make_shared(element::f32, Shape{1, 15, 128}); - auto indices = opset7::Constant::create(element::i32, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {1}); - - auto gather = std::make_shared(data, indices, axis, 0); - - model = std::make_shared(NodeVector{gather}, ParameterVector{data}); - - manager.register_pass(); - } - - { - auto indices_type = element::i32; - - auto data = std::make_shared(element::f32, Shape{1, 15, 128}); - auto indices = opset7::Constant::create(indices_type, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {1}); - - auto shape_of = std::make_shared(data, indices_type); - auto input_gather = std::make_shared(shape_of, - opset7::Constant::create(indices_type, Shape{}, {1}), - opset7::Constant::create(indices_type, Shape{}, {0})); - auto add = std::make_shared(input_gather, indices); - OPENVINO_SUPPRESS_DEPRECATED_START - auto const_add = get_constant_from_source(add); - OPENVINO_SUPPRESS_DEPRECATED_END - if (const_add == nullptr) - OPENVINO_THROW("indices should've been constant folded"); - auto gather = std::make_shared(data, const_add, axis); - - model_ref = std::make_shared(NodeVector{gather}, ParameterVector{data}); - } -} - -TEST_F(TransformationTestsF, GatherNegativeIndicesNormalize_neg_axis) { - { - auto data = std::make_shared(element::f32, Shape{1, 15, 128}); - auto indices = opset7::Constant::create(element::i32, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {-2}); - - auto gather = std::make_shared(data, indices, axis, 0); - - model = std::make_shared(NodeVector{gather}, ParameterVector{data}); - - manager.register_pass(); - } - - { - auto indices_type = element::i32; - - auto data = std::make_shared(element::f32, Shape{1, 15, 128}); - auto indices = opset7::Constant::create(indices_type, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {-2}); - - auto shape_of = std::make_shared(data, indices_type); - auto input_gather = std::make_shared(shape_of, - opset7::Constant::create(indices_type, Shape{}, {1}), - opset7::Constant::create(indices_type, Shape{}, {0})); - auto add = std::make_shared(input_gather, indices); - OPENVINO_SUPPRESS_DEPRECATED_START - auto const_add = get_constant_from_source(add); - OPENVINO_SUPPRESS_DEPRECATED_END - if (const_add == nullptr) - OPENVINO_THROW("indices should've been constant folded"); - auto gather = std::make_shared(data, const_add, axis); - - model_ref = std::make_shared(NodeVector{gather}, ParameterVector{data}); - } -} - -TEST_F(TransformationTestsF, GatherNegativeIndicesNormalize_dif_input_types) { - { - auto data = std::make_shared(element::f32, Shape{1, 15, 128}); - auto indices = opset7::Constant::create(element::i32, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i64, Shape{}, {1}); - - auto gather = std::make_shared(data, indices, axis, 0); - - model = std::make_shared(NodeVector{gather}, ParameterVector{data}); - - manager.register_pass(); - } - - { - auto indices_type = element::i32; - - auto data = std::make_shared(element::f32, Shape{1, 15, 128}); - auto indices = opset7::Constant::create(indices_type, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i64, Shape{}, {1}); - - auto shape_of = std::make_shared(data, indices_type); - auto input_gather = std::make_shared(shape_of, - opset7::Constant::create(indices_type, Shape{}, {1}), - opset7::Constant::create(indices_type, Shape{}, {0})); - auto add = std::make_shared(input_gather, indices); - OPENVINO_SUPPRESS_DEPRECATED_START - auto const_add = get_constant_from_source(add); - OPENVINO_SUPPRESS_DEPRECATED_END - if (const_add == nullptr) - OPENVINO_THROW("indices should've been constant folded"); - auto gather = std::make_shared(data, const_add, axis); - - model_ref = std::make_shared(NodeVector{gather}, ParameterVector{data}); - } -} - -TEST_F(TransformationTestsF, GatherNegativeIndicesNormalize_static_axis_dim) { - { - auto data = std::make_shared(element::f32, PartialShape{DYN, 15, DYN}); - auto indices = opset7::Constant::create(element::i32, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {1}); - - auto gather = std::make_shared(data, indices, axis, 0); - - model = std::make_shared(NodeVector{gather}, ParameterVector{data}); - - manager.register_pass(); - } - - { - auto indices_type = element::i32; - - auto data = std::make_shared(element::f32, PartialShape{DYN, 15, DYN}); - auto indices = opset7::Constant::create(indices_type, Shape{}, {2}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {1}); - - auto gather = std::make_shared(data, indices, axis); - model_ref = std::make_shared(NodeVector{gather}, ParameterVector{data}); - } -} - -TEST_F(TransformationTestsF, GatherNegativeIndicesNormalize_static_axis_dim_neg_axis) { - { - auto data = std::make_shared(element::f32, PartialShape{DYN, 15, DYN}); - auto indices = opset7::Constant::create(element::i32, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {-2}); - - auto gather = std::make_shared(data, indices, axis, 0); - - model = std::make_shared(NodeVector{gather}, ParameterVector{data}); - - manager.register_pass(); - } - - { - auto indices_type = element::i32; - - auto data = std::make_shared(element::f32, PartialShape{DYN, 15, DYN}); - auto indices = opset7::Constant::create(indices_type, Shape{}, {2}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {-2}); - - auto gather = std::make_shared(data, indices, axis); - - model_ref = std::make_shared(NodeVector{gather}, ParameterVector{data}); - } -} - -TEST_F(TransformationTestsF, GatherNegativeIndicesNormalize_non_static_axis_dim) { - { - auto data = std::make_shared(element::f32, PartialShape{DYN, DYN, DYN}); - auto indices = opset7::Constant::create(element::i32, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {1}); - - auto gather = std::make_shared(data, indices, axis, 0); - - model = std::make_shared(NodeVector{gather}, ParameterVector{data}); - - manager.register_pass(); - } - - { - auto indices_type = element::i32; - - auto data = std::make_shared(element::f32, PartialShape{DYN, DYN, DYN}); - auto indices = opset7::Constant::create(indices_type, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {1}); - - auto gather = std::make_shared(data, indices, axis); - - model_ref = std::make_shared(NodeVector{gather}, ParameterVector{data}); - } -} - -TEST_F(TransformationTestsF, GatherNegativeIndicesNormalize_positive_ind) { - { - auto data = std::make_shared(element::f32, Shape{2, 3}); - auto indices = opset7::Constant::create(element::i32, Shape{}, {1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {0}); - - auto gather = std::make_shared(data, indices, axis, 0); - - model = std::make_shared(NodeVector{gather}, ParameterVector{data}); - - manager.register_pass(); - } - - { - auto data = std::make_shared(element::f32, Shape{2, 3}); - auto indices = opset7::Constant::create(element::i32, Shape{}, {1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {0}); - - auto gather = std::make_shared(data, indices, axis); - - model_ref = std::make_shared(NodeVector{gather}, ParameterVector{data}); - } -} - -TEST_F(TransformationTestsF, GatherNegativeIndicesNormalize_non_static_rank) { - { - auto data = std::make_shared(element::f32, PartialShape::dynamic(Rank::dynamic())); - auto indices = opset7::Constant::create(element::i32, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {0}); - - auto gather = std::make_shared(data, indices, axis, 0); - - model = std::make_shared(NodeVector{gather}, ParameterVector{data}); - - manager.register_pass(); - } - - { - auto data = std::make_shared(element::f32, PartialShape::dynamic()); - auto indices = opset7::Constant::create(element::i32, Shape{}, {-1}); - auto axis = opset7::Constant::create(element::i32, Shape{}, {0}); - - auto gather = std::make_shared(data, indices, axis); - - model_ref = std::make_shared(NodeVector{gather}, ParameterVector{data}); - } -} diff --git a/src/plugins/intel_cpu/tests/functional/shared_tests_instances/single_layer_tests/gather.cpp b/src/plugins/intel_cpu/tests/functional/shared_tests_instances/single_layer_tests/gather.cpp index b82cadb87d9..68a16954a19 100644 --- a/src/plugins/intel_cpu/tests/functional/shared_tests_instances/single_layer_tests/gather.cpp +++ b/src/plugins/intel_cpu/tests/functional/shared_tests_instances/single_layer_tests/gather.cpp @@ -9,6 +9,7 @@ namespace { using ov::test::Gather7LayerTest; using ov::test::Gather8LayerTest; +using ov::test::Gather8withIndicesDataLayerTest; const std::vector model_types = { ov::element::f32, @@ -203,4 +204,29 @@ const auto gatherParamsVec3 = testing::Combine( INSTANTIATE_TEST_CASE_P(smoke_Vec3, Gather8LayerTest, gatherParamsVec3, Gather8LayerTest::getTestCaseName); + +const ov::test::gather7ParamsTuple dummyParams = { + ov::test::static_shapes_to_test_representation(std::vector{{2, 3}}), // input shape + ov::Shape{2, 2}, // indices shape + std::tuple{1, 1}, // axis, batch + ov::element::f32, // model type + ov::test::utils::DEVICE_CPU // device +}; + +const std::vector> indicesData = { + {0, 1, 2, 0}, // positive in bound + {-1, -2, -3, -1}, // negative in bound + {-1, 0, 1, 2}, // positive and negative in bound + {0, 1, 2, 3}, // positive out of bound + {-1, -2, -3, -4}, // negative out of bound + {0, 4, -4, 0}, // positive and negative out of bound +}; + +const auto gatherWithIndicesParams = testing::Combine( + testing::Values(dummyParams), + testing::ValuesIn(indicesData) +); + +INSTANTIATE_TEST_CASE_P(smoke, Gather8withIndicesDataLayerTest, gatherWithIndicesParams, Gather8withIndicesDataLayerTest::getTestCaseName); + } // namespace diff --git a/src/plugins/intel_cpu/tests/functional/shared_tests_instances/skip_tests_config.cpp b/src/plugins/intel_cpu/tests/functional/shared_tests_instances/skip_tests_config.cpp index 127002565e2..bc4b9786d15 100644 --- a/src/plugins/intel_cpu/tests/functional/shared_tests_instances/skip_tests_config.cpp +++ b/src/plugins/intel_cpu/tests/functional/shared_tests_instances/skip_tests_config.cpp @@ -177,8 +177,6 @@ std::vector disabledTestPatterns() { R"(.*(Hetero).*InferRequestPreprocessTest.*SetPreProcessToInferRequest.*)", // TODO: for 22.2 (Issue 68949) R"(.*smoke_AutoBatching_CPU/AutoBatching_Test_DetectionOutput.*)", - // Issue: 117837 - R"(.*smoke_4D_out_of_range/GatherInPlaceLayerTestCPU.*_indices=\(\-15\).*)", // Issue: 120222 R"(.*smoke_TopK/TopKLayerTest.Inference.*_k=1_axis=3_.*_modelType=f16_trgDev=CPU.*)", R"(.*smoke_TopK/TopKLayerTest.Inference.*_k=7_axis=3_.*_modelType=f16_trgDev=CPU.*)", diff --git a/src/plugins/intel_gpu/tests/functional/shared_tests_instances/single_layer_tests/gather.cpp b/src/plugins/intel_gpu/tests/functional/shared_tests_instances/single_layer_tests/gather.cpp index 4ab3baadfab..04b501af6d6 100644 --- a/src/plugins/intel_gpu/tests/functional/shared_tests_instances/single_layer_tests/gather.cpp +++ b/src/plugins/intel_gpu/tests/functional/shared_tests_instances/single_layer_tests/gather.cpp @@ -578,4 +578,32 @@ INSTANTIATE_TEST_SUITE_P( Gather8IndiceScalarLayerTest::getTestCaseName ); +gather7ParamsTuple dummyParams = { + std::vector{2, 3}, + std::vector{2, 2}, + std::tuple{1, 1}, + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::UNSPECIFIED, + InferenceEngine::Precision::UNSPECIFIED, + InferenceEngine::Layout::ANY, + InferenceEngine::Layout::ANY, + ov::test::utils::DEVICE_GPU, +}; + +std::vector> indicesData = { + {0, 1, 2, 0}, // positive in bound + {-1, -2, -3, -1}, // negative in bound + {-1, 0, 1, 2}, // positive and negative in bound + {0, 1, 2, 3}, // positive out of bound + {-1, -2, -3, -4}, // negative out of bound + {0, 4, -4, 0}, // positive and negative out of bound +}; + +const auto gatherWithIndicesParams = testing::Combine( + testing::Values(dummyParams), + testing::ValuesIn(indicesData) +); + +INSTANTIATE_TEST_CASE_P(smoke, Gather8withIndicesDataLayerTest, gatherWithIndicesParams, Gather8withIndicesDataLayerTest::getTestCaseName); + } // namespace diff --git a/src/tests/functional/plugin/shared/include/single_layer_tests/gather.hpp b/src/tests/functional/plugin/shared/include/single_layer_tests/gather.hpp index f6b8f091bd8..e909283ff31 100644 --- a/src/tests/functional/plugin/shared/include/single_layer_tests/gather.hpp +++ b/src/tests/functional/plugin/shared/include/single_layer_tests/gather.hpp @@ -24,4 +24,8 @@ TEST_P(Gather8IndiceScalarLayerTest, CompareWithRefs) { Run(); }; +TEST_P(Gather8withIndicesDataLayerTest, CompareWithRefs) { + Run(); +}; + } // namespace LayerTestsDefinitions diff --git a/src/tests/functional/plugin/shared/include/single_op_tests/gather.hpp b/src/tests/functional/plugin/shared/include/single_op_tests/gather.hpp index 6c27459fc18..be9aa740776 100644 --- a/src/tests/functional/plugin/shared/include/single_op_tests/gather.hpp +++ b/src/tests/functional/plugin/shared/include/single_op_tests/gather.hpp @@ -23,5 +23,9 @@ TEST_P(Gather8LayerTest, Inference) { TEST_P(Gather8IndiceScalarLayerTest, Inference) { run(); }; + +TEST_P(Gather8withIndicesDataLayerTest, Inference) { + run(); +}; } // namespace test } // namespace ov diff --git a/src/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/gather.hpp b/src/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/gather.hpp index 5f9e9473708..c2f354f3920 100644 --- a/src/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/gather.hpp +++ b/src/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/gather.hpp @@ -83,4 +83,18 @@ protected: void SetUp() override; }; +typedef std::tuple< + gather7ParamsTuple, + std::vector // indices data +> gather8withIndicesDataParamsTuple; + +class Gather8withIndicesDataLayerTest : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(const testing::TestParamInfo& obj); + +protected: + void SetUp() override; +}; + } // namespace LayerTestsDefinitions diff --git a/src/tests/functional/shared_test_classes/include/shared_test_classes/single_op/gather.hpp b/src/tests/functional/shared_test_classes/include/shared_test_classes/single_op/gather.hpp index 36d6ba48dfd..a41a13ce962 100644 --- a/src/tests/functional/shared_test_classes/include/shared_test_classes/single_op/gather.hpp +++ b/src/tests/functional/shared_test_classes/include/shared_test_classes/single_op/gather.hpp @@ -63,5 +63,20 @@ public: protected: void SetUp() override; }; + +typedef std::tuple< + gather7ParamsTuple, + std::vector // indices data +> gather8withIndicesDataParamsTuple; + +class Gather8withIndicesDataLayerTest : public testing::WithParamInterface, + virtual public ov::test::SubgraphBaseTest { +public: + static std::string getTestCaseName(const testing::TestParamInfo& obj); + +protected: + void SetUp() override; +}; + } // namespace test } // namespace ov diff --git a/src/tests/functional/shared_test_classes/src/single_layer/gather.cpp b/src/tests/functional/shared_test_classes/src/single_layer/gather.cpp index a9b58ecea05..97538823dc5 100644 --- a/src/tests/functional/shared_test_classes/src/single_layer/gather.cpp +++ b/src/tests/functional/shared_test_classes/src/single_layer/gather.cpp @@ -178,4 +178,56 @@ void Gather8IndiceScalarLayerTest::SetUp() { function = std::make_shared(results, functionParams, "gather"); } +std::string Gather8withIndicesDataLayerTest::getTestCaseName(const testing::TestParamInfo& obj) { + gather7ParamsTuple basicParams; + std::vector indicesData; + std::tie(basicParams, indicesData) = obj.param; + + std::tuple axis_batchIdx; + std::vector indices; + std::vector indicesShape, inputShape; + InferenceEngine::Precision netPrecision; + InferenceEngine::Precision inPrc, outPrc; + InferenceEngine::Layout inLayout, outLayout; + std::string targetName; + std::tie(inputShape, indicesShape, axis_batchIdx, netPrecision, inPrc, outPrc, inLayout, outLayout, targetName) = basicParams; + std::ostringstream result; + result << "IS=" << ov::test::utils::vec2str(inputShape) << "_"; + result << "indicesShape=" << ov::test::utils::vec2str(indicesShape) << "_"; + result << "axis=" << std::get<0>(axis_batchIdx) << "_"; + result << "batchIdx=" << std::get<1>(axis_batchIdx) << "_"; + result << "netPRC=" << netPrecision.name() << "_"; + result << "inPRC=" << inPrc.name() << "_"; + result << "outPRC=" << outPrc.name() << "_"; + result << "inL=" << inLayout << "_"; + result << "outL=" << outLayout << "_"; + result << "trgDev=" << targetName << "_"; + + result << "indicesData=" << ov::test::utils::vec2str(indicesData) << "_"; + + return result.str(); +} + +void Gather8withIndicesDataLayerTest::SetUp() { + gather7ParamsTuple basicParams; + std::vector indicesData; + std::tie(basicParams, indicesData) = GetParam(); + + std::tuple axis_batchIdx; + std::vector indicesShape; + std::vector inputShape; + InferenceEngine::Precision netPrecision; + std::tie(inputShape, indicesShape, axis_batchIdx, netPrecision, inPrc, outPrc, inLayout, outLayout, targetDevice) = basicParams; + int axis = std::get<0>(axis_batchIdx); + int batchIdx = std::get<1>(axis_batchIdx); + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + ov::ParameterVector functionParams {std::make_shared(ngPrc, ov::Shape(inputShape))}; + auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(functionParams)); + auto indicesNode = ngraph::builder::makeConstant(ngraph::element::i64, indicesShape, indicesData); + auto axisNode = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape({}), { axis }); + auto gather = std::make_shared(paramOuts[0], indicesNode, axisNode, batchIdx); + ngraph::ResultVector results{ std::make_shared(gather) }; + function = std::make_shared(results, functionParams, "gather"); +} + } // namespace LayerTestsDefinitions diff --git a/src/tests/functional/shared_test_classes/src/single_op/gather.cpp b/src/tests/functional/shared_test_classes/src/single_op/gather.cpp index 0dad09af952..f4c91752190 100644 --- a/src/tests/functional/shared_test_classes/src/single_op/gather.cpp +++ b/src/tests/functional/shared_test_classes/src/single_op/gather.cpp @@ -167,5 +167,76 @@ void Gather8IndiceScalarLayerTest::SetUp() { auto result = std::make_shared(gather); function = std::make_shared(result, ov::ParameterVector{param}, "gather"); } + +std::string Gather8withIndicesDataLayerTest::getTestCaseName(const testing::TestParamInfo& obj) { + gather7ParamsTuple basicParams; + std::vector indicesData; + std::tie(basicParams, indicesData) = obj.param; + + std::tuple axis_batch_idx; + std::vector indices; + ov::Shape indices_shape; + std::vector shapes; + ov::element::Type model_type; + std::string device_name; + std::tie(shapes, indices_shape, axis_batch_idx, model_type, device_name) = basicParams; + + std::ostringstream result; + result << "IS=("; + for (size_t i = 0lu; i < shapes.size(); i++) { + result << ov::test::utils::partialShape2str({shapes[i].first}) << (i < shapes.size() - 1lu ? "_" : ""); + } + result << ")_TS="; + for (size_t i = 0lu; i < shapes.front().second.size(); i++) { + result << "{"; + for (size_t j = 0lu; j < shapes.size(); j++) { + result << ov::test::utils::vec2str(shapes[j].second[i]) << (j < shapes.size() - 1lu ? "_" : ""); + } + result << "}_"; + } + result << "axis=" << std::get<0>(axis_batch_idx) << "_"; + result << "batch_idx=" << std::get<1>(axis_batch_idx) << "_"; + result << "indices_shape=" << ov::test::utils::vec2str(indices_shape) << "_"; + result << "netPRC=" << model_type.get_type_name() << "_"; + result << "trgDev=" << device_name << "_"; + + result << "indicesData=" << ov::test::utils::vec2str(indicesData) << "_"; + + return result.str(); +} + +void Gather8withIndicesDataLayerTest::SetUp() { + gather7ParamsTuple basicParams; + std::vector indicesData; + std::tie(basicParams, indicesData) = GetParam(); + + std::tuple axis_batch_idx; + ov::Shape indices_shape; + std::vector shapes; + ov::element::Type model_type; + std::tie(shapes, indices_shape, axis_batch_idx, model_type, targetDevice) = basicParams; + init_input_shapes(shapes); + + int axis = std::get<0>(axis_batch_idx); + int batch_idx = std::get<1>(axis_batch_idx); + + auto param = std::make_shared(model_type, inputDynamicShapes.front()); + + // create indices tensor and fill data + ov::Tensor indices_node_tensor{ov::element::i64, indices_shape}; + auto indices_tensor_data = indices_node_tensor.data(); + for (size_t i = 0; i < shape_size(indices_shape); i++) { + indices_tensor_data[i] = indicesData[i]; + } + + auto indices_node = std::make_shared(indices_node_tensor); + auto axis_node = ov::op::v0::Constant::create(ov::element::i64, ov::Shape(), {axis}); + + auto gather = std::make_shared(param, indices_node, axis_node, batch_idx); + + auto result = std::make_shared(gather); + function = std::make_shared(result, ov::ParameterVector{param}, "gather"); +} + } // namespace test } // namespace ov