From 8518a3a8e87815899b0cc8e0e071f1c8509f8bfe Mon Sep 17 00:00:00 2001 From: Kelvin Choi Date: Fri, 24 Mar 2023 15:12:12 +0900 Subject: [PATCH] [GPU] Disable converting gather8 to 7 pass because GPU plugin supports gather8:nagative-index feature (#15868) * Add GatherV7 and gatherV8 for convert_gather_0d pattern * Add updating output_shape using reorder/reshape for scalar indice instead of using ConvertGather0D pass * Add WA for NMS-gather8 pattern --- .../op_conversions/convert_gather_0d.cpp | 2 + .../intel_gpu/src/plugin/ops/constant.cpp | 2 + .../intel_gpu/src/plugin/ops/gather.cpp | 60 +++++++++++++++++++ .../src/plugin/transformations_pipeline.cpp | 4 +- .../single_layer_tests/gather.cpp | 19 ++++++ .../skip_tests_config.cpp | 2 - .../include/single_layer_tests/gather.hpp | 4 ++ .../single_layer/gather.hpp | 9 +++ .../src/single_layer/gather.cpp | 42 +++++++++++++ 9 files changed, 141 insertions(+), 3 deletions(-) diff --git a/src/common/transformations/src/transformations/op_conversions/convert_gather_0d.cpp b/src/common/transformations/src/transformations/op_conversions/convert_gather_0d.cpp index eca3823bf9b..86f10208c05 100644 --- a/src/common/transformations/src/transformations/op_conversions/convert_gather_0d.cpp +++ b/src/common/transformations/src/transformations/op_conversions/convert_gather_0d.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include "itt.hpp" diff --git a/src/plugins/intel_gpu/src/plugin/ops/constant.cpp b/src/plugins/intel_gpu/src/plugin/ops/constant.cpp index 1714e50e5da..e9bd5860f94 100644 --- a/src/plugins/intel_gpu/src/plugin/ops/constant.cpp +++ b/src/plugins/intel_gpu/src/plugin/ops/constant.cpp @@ -108,6 +108,8 @@ static void CreateConstantOp(Program& p, const std::shared_ptr(outOp) || + ngraph::is_type(outOp) || + ngraph::is_type(outOp) || ngraph::is_type(outOp) || ngraph::is_type(outOp)) { consts[op].needsBatchInterpretation = constDims.size() == 1; diff --git a/src/plugins/intel_gpu/src/plugin/ops/gather.cpp b/src/plugins/intel_gpu/src/plugin/ops/gather.cpp index addc556369b..c7eebb713d3 100644 --- a/src/plugins/intel_gpu/src/plugin/ops/gather.cpp +++ b/src/plugins/intel_gpu/src/plugin/ops/gather.cpp @@ -9,7 +9,9 @@ #include "intel_gpu/primitives/gather.hpp" #include "intel_gpu/primitives/reorder.hpp" +#include "intel_gpu/primitives/reshape.hpp" +using namespace InferenceEngine; namespace ov { namespace intel_gpu { @@ -46,6 +48,43 @@ void CreateGatherOpBase(Program& p, const std::shared_ptr& op, const int64_t // Dynamic path will do shape infer internally, so no need to pass valid out shape for that case ov::Shape out_shape = op->get_output_partial_shape(0).is_static() ? op->get_output_shape(0) : ov::Shape{}; + // Update output_shape in case of scalar indice + bool need_reshape = false; + auto out_shape_original = out_shape; + if (!p.use_new_shape_infer() && op->get_output_partial_shape(0).is_static()) { + auto input1_shape = op->get_input_shape(1); + if (input1_shape.size() == 0 && batch_dim == 0) { + need_reshape = true; + + auto new_axis = axis; + if (new_axis < 0) { + new_axis += op->get_input_shape(0).size(); + } + out_shape.push_back(1); + for (int i = out_shape.size() - 1; i > new_axis ; i--) { + out_shape[i] = out_shape[i-1]; + } + out_shape[new_axis] = 1; + } + } + + // WA for NMS->Gather construction. NMS fills part of the output blob by the -1 if these values + // must not be taken into account. + // CPU also uses this like of WA. + if (support_neg_ind) { + const auto& rti = op->get_rt_info(); + const auto& reverse = rti.find("dontReverseIndices"); + if (reverse != rti.end()) { + support_neg_ind = false; + } + } + + // gather + auto reshapeName = layerName + ""; + if (need_reshape) { + layerName = layerName + "_reshape_output"; + } + auto gatherPrim = cldnn::gather(layerName, reordered_inputs[0], reordered_inputs[1], @@ -55,6 +94,27 @@ void CreateGatherOpBase(Program& p, const std::shared_ptr& op, const int64_t support_neg_ind); p.add_primitive(*op, gatherPrim); + + // Add reorder and reshape for scalar indice + if (need_reshape) { + auto input = inputs[0]; + input.pid = layerName; + + auto targetFormat = cldnn::format::get_default_format(out_shape_original.size()); + if (targetFormat.value != cldnn::format::get_default_format(out_shape.size()).value) { + auto reorderName = layerName + "_cldnn_in_reorder"; + auto targetDatatype = cldnn::element_type_to_data_type(op->get_input_element_type(0)); + auto reorderPrim = cldnn::reorder(reorderName, + input, + targetFormat, + targetDatatype); + p.add_primitive(*op, reorderPrim); + input.pid = reorderName; + } + + auto reshapePrim = cldnn::reshape(reshapeName, input, tensor_from_dims(out_shape_original)); + p.add_primitive(*op, reshapePrim); + } } static void CreateGatherOp(Program& p, const std::shared_ptr& op) { diff --git a/src/plugins/intel_gpu/src/plugin/transformations_pipeline.cpp b/src/plugins/intel_gpu/src/plugin/transformations_pipeline.cpp index 78ccd48ab34..7ce86295f1c 100644 --- a/src/plugins/intel_gpu/src/plugin/transformations_pipeline.cpp +++ b/src/plugins/intel_gpu/src/plugin/transformations_pipeline.cpp @@ -421,8 +421,10 @@ void TransformationsPipeline::apply(std::shared_ptr func) { pass_config->disable(); pass_config->disable(); pass_config->disable(); - pass_config->enable(); pass_config->disable(); + pass_config->disable(); + pass_config->disable(); + pass_config->enable(); if (enableInt8) { diff --git a/src/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gather.cpp b/src/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gather.cpp index 3e327087555..84d8e889d1f 100644 --- a/src/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gather.cpp +++ b/src/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gather.cpp @@ -78,6 +78,18 @@ const std::vector> inputShapesAxes4b2 = { std::vector{2, 3, 7, 8, 4}, }; +const auto GatherIndiceScalar = []() { + return testing::Combine(testing::Values(std::vector{1, 3, 4, 5}), + testing::Values(std::vector{}), + testing::Values(std::tuple(2, 0)), + testing::Values(InferenceEngine::Precision::FP32), + 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)); +}; + const auto GatherAxes4i4b1 = []() { return testing::Combine(testing::ValuesIn(inputShapesAxes4b1), testing::ValuesIn(indicesShapes2), @@ -182,6 +194,13 @@ INSTANTIATE_TEST_SUITE_P( Gather8LayerTest::getTestCaseName ); +INSTANTIATE_TEST_SUITE_P( + smoke_GatherIndiceScalar, + Gather8IndiceScalarLayerTest, + GatherIndiceScalar(), + Gather8IndiceScalarLayerTest::getTestCaseName +); + const std::vector> indices = { std::vector{0, 3, 2, 1}, }; diff --git a/src/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp b/src/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp index 577dcc72366..df4e53897f4 100644 --- a/src/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp +++ b/src/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp @@ -58,8 +58,6 @@ std::vector disabledTestPatterns() { R"(.*Behavior.*OVInferRequestIOTensorTest.*canInferAfterIOBlobReallocation.*)", R"(.*Behavior.*OVInferRequestDynamicTests.*InferUpperBoundNetworkAfterIOTensorsReshaping.*)", R"(.*(Auto|Multi).*Behavior.*IncorrectConfigTests.*CanNotLoadNetworkWithIncorrectConfig.*)", - // TODO: until issue is xxx-59670 is resolved - R"(.*Gather8LayerTest.*)", // Not implemented yet: R"(.*Behavior.*ExecutableNetworkBaseTest.*canSetConfigToExecNet.*)", R"(.*Behavior.*ExecutableNetworkBaseTest.*canExport.*)", 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 b992387da08..f6b8f091bd8 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 @@ -20,4 +20,8 @@ TEST_P(Gather8LayerTest, CompareWithRefs) { Run(); }; +TEST_P(Gather8IndiceScalarLayerTest, CompareWithRefs) { + Run(); +}; + } // namespace LayerTestsDefinitions 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 ce3a4105cc6..5dcc649a415 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 @@ -74,4 +74,13 @@ protected: void SetUp() override; }; +class Gather8IndiceScalarLayerTest : 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/src/single_layer/gather.cpp b/src/tests/functional/shared_test_classes/src/single_layer/gather.cpp index 8ce59926dbc..123ada7a73e 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 @@ -136,4 +136,46 @@ void Gather8LayerTest::SetUp() { function = std::make_shared(results, functionParams, "gather"); } +std::string Gather8IndiceScalarLayerTest::getTestCaseName(const testing::TestParamInfo& obj) { + 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) = obj.param; + std::ostringstream result; + result << "IS=" << CommonTestUtils::vec2str(inputShape) << "_"; + result << "indicesShape=" << CommonTestUtils::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 << "_"; + return result.str(); +} + +void Gather8IndiceScalarLayerTest::SetUp() { + 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) = GetParam(); + int axis = std::get<0>(axis_batchIdx); + int batchIdx = std::get<1>(axis_batchIdx); + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto functionParams = ngraph::builder::makeParams(ngPrc, { inputShape }); + auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(functionParams)); + auto indicesNode = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{}, {inputShape[axis] - 1})->output(0); + + 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