From 5c0f38f83f62fdabcdc980fa6dc3ed1ea16c8a05 Mon Sep 17 00:00:00 2001 From: Piotr Kowalczyk Date: Wed, 29 May 2024 13:17:49 +0200 Subject: [PATCH] [GPU][ROIAlignRotated]: Fixed a bug with wrong batch indexing and added functional test for the op (#24736) This is a follow up to #23955 ### Details: - Added functional test for ROI Align Rotated - Fixed a "bug" with wrong batch index inside cl kernel revealed by functional test for ROI Align Rotated. ### Tickets: - *[141877](https://jira.devtools.intel.com/browse/CVS-141877)* --- .../intel_gpu/src/plugin/ops/constant.cpp | 4 +- .../single_layer_tests/roi_align_rotated.cpp | 40 +++++ .../single_op_tests/roi_align_rotated.hpp | 15 ++ .../single_op/roi_align_rotated.hpp | 30 ++++ .../src/single_op/roi_align_rotated.cpp | 138 ++++++++++++++++++ .../tests_data/roi_align_rotated_data.h | 22 +++ 6 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 src/plugins/intel_gpu/tests/functional/shared_tests_instances/single_layer_tests/roi_align_rotated.cpp create mode 100644 src/tests/functional/plugin/shared/include/single_op_tests/roi_align_rotated.hpp create mode 100644 src/tests/functional/shared_test_classes/include/shared_test_classes/single_op/roi_align_rotated.hpp create mode 100644 src/tests/functional/shared_test_classes/src/single_op/roi_align_rotated.cpp diff --git a/src/plugins/intel_gpu/src/plugin/ops/constant.cpp b/src/plugins/intel_gpu/src/plugin/ops/constant.cpp index 838ee29d3acb3e..ec48aff9736a9a 100644 --- a/src/plugins/intel_gpu/src/plugin/ops/constant.cpp +++ b/src/plugins/intel_gpu/src/plugin/ops/constant.cpp @@ -17,6 +17,7 @@ #include "openvino/op/split.hpp" #include "openvino/op/prelu.hpp" #include "openvino/op/roi_align.hpp" +#include "openvino/op/roi_align_rotated.hpp" #include "openvino/op/variadic_split.hpp" #include "openvino/op/util/op_types.hpp" #include "openvino/op/loop.hpp" @@ -221,7 +222,8 @@ static void CreateConstantOp(ProgramBuilder& p, const std::shared_ptr(outOp) || ov::is_type(outOp)) { + } else if (ov::is_type(outOp) || ov::is_type(outOp) || + ov::is_type(outOp)) { //< Hacks... consts[op].needsBatchInterpretation = constDims.size() == 1; } else if ((ov::is_type(outOp) || ov::is_type(outOp))) { // when inner network has 1d parameter which is connected to outer loop's constant 1d data, diff --git a/src/plugins/intel_gpu/tests/functional/shared_tests_instances/single_layer_tests/roi_align_rotated.cpp b/src/plugins/intel_gpu/tests/functional/shared_tests_instances/single_layer_tests/roi_align_rotated.cpp new file mode 100644 index 00000000000000..fb94ef2a842d99 --- /dev/null +++ b/src/plugins/intel_gpu/tests/functional/shared_tests_instances/single_layer_tests/roi_align_rotated.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +#include "single_op_tests/roi_align_rotated.hpp" + +#include "common_test_utils/test_constants.hpp" + +namespace { +using ov::test::ROIAlignRotatedLayerTest; + +const std::vector netPRCs = { + ov::element::f32 + // There is no possibility to test ROIAlign in fp16 precision, + // because on edge cases where in fp32 version ROI value is + // a little bit smaller than the nearest integer value, + // it would be bigger than the nearest integer in fp16 precision. + // Such behavior leads to completely different results of ROIAlign + // in fp32 and fp16 precisions. + // In real AI applications this problem is solved by precision-aware training. + + // ov::element::f16 +}; + +INSTANTIATE_TEST_SUITE_P(gtest_smoke_TestsROIAlignRotatedROIAlignLayerTest_EvalGenerateName_, + ROIAlignRotatedLayerTest, + ::testing::Combine(::testing::ValuesIn(ov::test::static_shapes_to_test_representation( + std::vector>{{{3, 8, 16, 16}}, + {{2, 1, 16, 10}}, + {{4, 3, 5, 12}}})), + ::testing::ValuesIn(std::vector{2, 4}), + ::testing::Values(2), + ::testing::Values(2), + ::testing::Values(2), + ::testing::ValuesIn(std::vector{1, 0.625}), + ::testing::ValuesIn(std::vector{true, false}), + ::testing::ValuesIn(netPRCs), + ::testing::Values(ov::test::utils::DEVICE_GPU)), + ROIAlignRotatedLayerTest::getTestCaseName); + +} // namespace diff --git a/src/tests/functional/plugin/shared/include/single_op_tests/roi_align_rotated.hpp b/src/tests/functional/plugin/shared/include/single_op_tests/roi_align_rotated.hpp new file mode 100644 index 00000000000000..67402ef9625d44 --- /dev/null +++ b/src/tests/functional/plugin/shared/include/single_op_tests/roi_align_rotated.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "shared_test_classes/single_op/roi_align_rotated.hpp" + +namespace ov { +namespace test { +TEST_P(ROIAlignRotatedLayerTest, Inference) { + run(); +} +} // namespace test +} // namespace ov diff --git a/src/tests/functional/shared_test_classes/include/shared_test_classes/single_op/roi_align_rotated.hpp b/src/tests/functional/shared_test_classes/include/shared_test_classes/single_op/roi_align_rotated.hpp new file mode 100644 index 00000000000000..6082e25f7e606e --- /dev/null +++ b/src/tests/functional/shared_test_classes/include/shared_test_classes/single_op/roi_align_rotated.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "shared_test_classes/base/ov_subgraph.hpp" + +namespace ov { +namespace test { +using roialignrotatedParams = std::tuple, // Feature map shape + int, // Num of Rois + int, // Pooled h + int, // Pooled w + int, // Sampling ratio + float, // Spatial scale + bool, // Clockwise mode + ov::element::Type, // Model type + ov::test::TargetDevice>; // Device name + +class ROIAlignRotatedLayerTest : 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_op/roi_align_rotated.cpp b/src/tests/functional/shared_test_classes/src/single_op/roi_align_rotated.cpp new file mode 100644 index 00000000000000..024820a0a79ea4 --- /dev/null +++ b/src/tests/functional/shared_test_classes/src/single_op/roi_align_rotated.cpp @@ -0,0 +1,138 @@ +// Copyright (C) 2018-2024 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/single_op/roi_align_rotated.hpp" + +#include + +#include "openvino/core/enum_names.hpp" + +namespace ov { +namespace test { + +static constexpr int ROI_DEF_SIZE = 5; +static constexpr int SEED = 7877; +static constexpr float PI = 3.14159265358979323846f; + +struct TestParams { + std::vector input_shapes; + int num_rois; + int pooled_h; + int pooled_w; + int sampliong_ratio; + float spatial_scale; + bool clockwise_mode; + ov::element::Type model_type; + std::string target_device; +}; + +static TestParams ExtractTestParams(const roialignrotatedParams& param) { + TestParams tp; + std::tie(tp.input_shapes, + tp.num_rois, + tp.pooled_h, + tp.pooled_w, + tp.sampliong_ratio, + tp.spatial_scale, + tp.clockwise_mode, + tp.model_type, + tp.target_device) = param; + return tp; +} + +static float RandomFloat(float low, float high) { + static std::default_random_engine engine(SEED); + std::uniform_real_distribution dis(low, high); + return dis(engine); +} + +static std::vector FillRoisTensor(int num_rois, int height, int width) { + std::vector rois; + rois.resize(num_rois * ROI_DEF_SIZE); + + for (int i = 0; i < rois.size() / ROI_DEF_SIZE; i++) { + // center_x, center_y, width, height, angle + rois[i * ROI_DEF_SIZE + 0] = RandomFloat(0.0f, width); + rois[i * ROI_DEF_SIZE + 1] = RandomFloat(0.0f, height); + rois[i * ROI_DEF_SIZE + 2] = RandomFloat(0.0f, width); + rois[i * ROI_DEF_SIZE + 3] = RandomFloat(0.0f, height); + rois[i * ROI_DEF_SIZE + 4] = RandomFloat(0.0f, 2 * PI); + } + + return rois; +} + +static std::vector FillBAtchIdxTensor(int num_rois, int batch_size) { + std::vector idx; + idx.resize(num_rois); + int batch_id = 0; + for (int i = 0; i < idx.size(); i++) { + idx[i] = batch_id; + batch_id = (batch_id + 1) % batch_size; + } + + return idx; +} + +std::string ROIAlignRotatedLayerTest::getTestCaseName(const testing::TestParamInfo& obj) { + const TestParams tp = ExtractTestParams(obj.param); + + std::ostringstream result; + result << "IS=("; + for (size_t i = 0lu; i < tp.input_shapes.size(); i++) { + result << ov::test::utils::partialShape2str({tp.input_shapes[i].first}) + << (i < tp.input_shapes.size() - 1lu ? "_" : ""); + } + result << ")_TS="; + for (size_t i = 0lu; i < tp.input_shapes.front().second.size(); i++) { + result << "{"; + for (size_t j = 0lu; j < tp.input_shapes.size(); j++) { + result << ov::test::utils::vec2str(tp.input_shapes[j].second[i]) + << (j < tp.input_shapes.size() - 1lu ? "_" : ""); + } + result << "}_"; + } + result << "numRois=" << tp.num_rois << "_"; + result << "pooledH=" << tp.pooled_h << "_"; + result << "pooledW=" << tp.pooled_w << "_"; + result << "samplingRatio=" << tp.sampliong_ratio << "_"; + result << "spatialScale=" << tp.spatial_scale << "_"; + result << "clockwiseMode=" << tp.clockwise_mode << "_"; + result << "modelType=" << tp.model_type.to_string() << "_"; + result << "trgDev=" << tp.target_device; + return result.str(); +} + +void ROIAlignRotatedLayerTest::SetUp() { + const TestParams tp = ExtractTestParams(this->GetParam()); + targetDevice = tp.target_device; + init_input_shapes(tp.input_shapes); + + const auto input_batch_size = inputDynamicShapes[0][0].get_length(); + const auto input_height = inputDynamicShapes[0][2].get_length(); + const auto input_width = inputDynamicShapes[0][3].get_length(); + + auto input = std::make_shared(tp.model_type, inputDynamicShapes[0]); + const auto rois_shape = ov::Shape{static_cast(tp.num_rois), ROI_DEF_SIZE}; + const auto rois_idx_shape = ov::Shape{static_cast(tp.num_rois)}; + + auto rois = std::make_shared(tp.model_type, + rois_shape, + FillRoisTensor(tp.num_rois, input_height, input_width).data()); + auto rois_idx = std::make_shared(ov::element::i32, + rois_idx_shape, + FillBAtchIdxTensor(tp.num_rois, input_batch_size).data()); + auto roi_align = std::make_shared(input, + rois, + rois_idx, + tp.pooled_h, + tp.pooled_w, + tp.sampliong_ratio, + tp.spatial_scale, + tp.clockwise_mode); + function = std::make_shared(roi_align->outputs(), ov::ParameterVector{input}, "roi_align_rotated"); +} + +} // namespace test +} // namespace ov diff --git a/src/tests/test_utils/unit_test_utils/tests_data/roi_align_rotated_data.h b/src/tests/test_utils/unit_test_utils/tests_data/roi_align_rotated_data.h index 54fe9d1ffe39cb..49b253fdb9619e 100644 --- a/src/tests/test_utils/unit_test_utils/tests_data/roi_align_rotated_data.h +++ b/src/tests/test_utils/unit_test_utils/tests_data/roi_align_rotated_data.h @@ -287,6 +287,28 @@ TEST_DATA(LIST(1, 1, 5, 5), LIST(0), LIST(5.1271, 1.2473, 6.1773, 2.9598, 7.2275, 3.2300, 8.2777, 3.7458, 9.3279, 4.4060), "roi_align_rotated_all_features"); +TEST_DATA(LIST(1, 1, 2, 5), + 2, + 2, + 1.0f, + 2, + true, + LIST(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), + LIST(0.5, 0.5, 1, 1, 0), + LIST(0), + LIST(1.0, 1.25, 2.25, 2.50), + "input_image_not_rectangular"); +TEST_DATA(LIST(2, 1, 2, 5), + 2, + 2, + 1.0f, + 2, + true, + LIST(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20), + LIST(0.5, 1., 2., 5., 0.5, 0., 2., 5., 1., 0.), + LIST(0, 1), + LIST(0.5201, 1.9866, 2.5219, 3.0896, 0.0000, 16.7500, 0.0000, 16.7500), + "input_image_not_rectangular_batch_2"); #undef PI #undef LIST