Skip to content

Commit 5c0f38f

Browse files
authored
[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)*
1 parent 6a8079b commit 5c0f38f

File tree

6 files changed

+248
-1
lines changed

6 files changed

+248
-1
lines changed

src/plugins/intel_gpu/src/plugin/ops/constant.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "openvino/op/split.hpp"
1818
#include "openvino/op/prelu.hpp"
1919
#include "openvino/op/roi_align.hpp"
20+
#include "openvino/op/roi_align_rotated.hpp"
2021
#include "openvino/op/variadic_split.hpp"
2122
#include "openvino/op/util/op_types.hpp"
2223
#include "openvino/op/loop.hpp"
@@ -221,7 +222,8 @@ static void CreateConstantOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v0
221222
if (constDims.size() == 4 && input_shape.size() == 3) { // In case of weight dim 4 and input dim 3,
222223
constDims.push_back(1); // The weight cldnn tensor adds 1d to the end as the input cldnn tensor does
223224
}
224-
} else if (ov::is_type<ov::op::v3::ROIAlign>(outOp) || ov::is_type<ov::op::v9::ROIAlign>(outOp)) {
225+
} else if (ov::is_type<ov::op::v3::ROIAlign>(outOp) || ov::is_type<ov::op::v9::ROIAlign>(outOp) ||
226+
ov::is_type<ov::op::v15::ROIAlignRotated>(outOp)) { //< Hacks...
225227
consts[op].needsBatchInterpretation = constDims.size() == 1;
226228
} else if ((ov::is_type<ov::op::v5::Loop>(outOp) || ov::is_type<ov::op::v0::TensorIterator>(outOp))) {
227229
// when inner network has 1d parameter which is connected to outer loop's constant 1d data,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (C) 2018-2024 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
#include "single_op_tests/roi_align_rotated.hpp"
5+
6+
#include "common_test_utils/test_constants.hpp"
7+
8+
namespace {
9+
using ov::test::ROIAlignRotatedLayerTest;
10+
11+
const std::vector<ov::element::Type> netPRCs = {
12+
ov::element::f32
13+
// There is no possibility to test ROIAlign in fp16 precision,
14+
// because on edge cases where in fp32 version ROI value is
15+
// a little bit smaller than the nearest integer value,
16+
// it would be bigger than the nearest integer in fp16 precision.
17+
// Such behavior leads to completely different results of ROIAlign
18+
// in fp32 and fp16 precisions.
19+
// In real AI applications this problem is solved by precision-aware training.
20+
21+
// ov::element::f16
22+
};
23+
24+
INSTANTIATE_TEST_SUITE_P(gtest_smoke_TestsROIAlignRotatedROIAlignLayerTest_EvalGenerateName_,
25+
ROIAlignRotatedLayerTest,
26+
::testing::Combine(::testing::ValuesIn(ov::test::static_shapes_to_test_representation(
27+
std::vector<std::vector<ov::Shape>>{{{3, 8, 16, 16}},
28+
{{2, 1, 16, 10}},
29+
{{4, 3, 5, 12}}})),
30+
::testing::ValuesIn(std::vector<int>{2, 4}),
31+
::testing::Values(2),
32+
::testing::Values(2),
33+
::testing::Values(2),
34+
::testing::ValuesIn(std::vector<float>{1, 0.625}),
35+
::testing::ValuesIn(std::vector<bool>{true, false}),
36+
::testing::ValuesIn(netPRCs),
37+
::testing::Values(ov::test::utils::DEVICE_GPU)),
38+
ROIAlignRotatedLayerTest::getTestCaseName);
39+
40+
} // namespace
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (C) 2018-2024 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#pragma once
6+
7+
#include "shared_test_classes/single_op/roi_align_rotated.hpp"
8+
9+
namespace ov {
10+
namespace test {
11+
TEST_P(ROIAlignRotatedLayerTest, Inference) {
12+
run();
13+
}
14+
} // namespace test
15+
} // namespace ov
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (C) 2018-2024 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#pragma once
6+
7+
#include "shared_test_classes/base/ov_subgraph.hpp"
8+
9+
namespace ov {
10+
namespace test {
11+
using roialignrotatedParams = std::tuple<std::vector<InputShape>, // Feature map shape
12+
int, // Num of Rois
13+
int, // Pooled h
14+
int, // Pooled w
15+
int, // Sampling ratio
16+
float, // Spatial scale
17+
bool, // Clockwise mode
18+
ov::element::Type, // Model type
19+
ov::test::TargetDevice>; // Device name
20+
21+
class ROIAlignRotatedLayerTest : public testing::WithParamInterface<roialignrotatedParams>,
22+
virtual public ov::test::SubgraphBaseTest {
23+
public:
24+
static std::string getTestCaseName(const testing::TestParamInfo<roialignrotatedParams>& obj);
25+
26+
protected:
27+
void SetUp() override;
28+
};
29+
} // namespace test
30+
} // namespace ov
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright (C) 2018-2024 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include "shared_test_classes/single_op/roi_align_rotated.hpp"
6+
7+
#include <random>
8+
9+
#include "openvino/core/enum_names.hpp"
10+
11+
namespace ov {
12+
namespace test {
13+
14+
static constexpr int ROI_DEF_SIZE = 5;
15+
static constexpr int SEED = 7877;
16+
static constexpr float PI = 3.14159265358979323846f;
17+
18+
struct TestParams {
19+
std::vector<InputShape> input_shapes;
20+
int num_rois;
21+
int pooled_h;
22+
int pooled_w;
23+
int sampliong_ratio;
24+
float spatial_scale;
25+
bool clockwise_mode;
26+
ov::element::Type model_type;
27+
std::string target_device;
28+
};
29+
30+
static TestParams ExtractTestParams(const roialignrotatedParams& param) {
31+
TestParams tp;
32+
std::tie(tp.input_shapes,
33+
tp.num_rois,
34+
tp.pooled_h,
35+
tp.pooled_w,
36+
tp.sampliong_ratio,
37+
tp.spatial_scale,
38+
tp.clockwise_mode,
39+
tp.model_type,
40+
tp.target_device) = param;
41+
return tp;
42+
}
43+
44+
static float RandomFloat(float low, float high) {
45+
static std::default_random_engine engine(SEED);
46+
std::uniform_real_distribution<float> dis(low, high);
47+
return dis(engine);
48+
}
49+
50+
static std::vector<float> FillRoisTensor(int num_rois, int height, int width) {
51+
std::vector<float> rois;
52+
rois.resize(num_rois * ROI_DEF_SIZE);
53+
54+
for (int i = 0; i < rois.size() / ROI_DEF_SIZE; i++) {
55+
// center_x, center_y, width, height, angle
56+
rois[i * ROI_DEF_SIZE + 0] = RandomFloat(0.0f, width);
57+
rois[i * ROI_DEF_SIZE + 1] = RandomFloat(0.0f, height);
58+
rois[i * ROI_DEF_SIZE + 2] = RandomFloat(0.0f, width);
59+
rois[i * ROI_DEF_SIZE + 3] = RandomFloat(0.0f, height);
60+
rois[i * ROI_DEF_SIZE + 4] = RandomFloat(0.0f, 2 * PI);
61+
}
62+
63+
return rois;
64+
}
65+
66+
static std::vector<int> FillBAtchIdxTensor(int num_rois, int batch_size) {
67+
std::vector<int> idx;
68+
idx.resize(num_rois);
69+
int batch_id = 0;
70+
for (int i = 0; i < idx.size(); i++) {
71+
idx[i] = batch_id;
72+
batch_id = (batch_id + 1) % batch_size;
73+
}
74+
75+
return idx;
76+
}
77+
78+
std::string ROIAlignRotatedLayerTest::getTestCaseName(const testing::TestParamInfo<roialignrotatedParams>& obj) {
79+
const TestParams tp = ExtractTestParams(obj.param);
80+
81+
std::ostringstream result;
82+
result << "IS=(";
83+
for (size_t i = 0lu; i < tp.input_shapes.size(); i++) {
84+
result << ov::test::utils::partialShape2str({tp.input_shapes[i].first})
85+
<< (i < tp.input_shapes.size() - 1lu ? "_" : "");
86+
}
87+
result << ")_TS=";
88+
for (size_t i = 0lu; i < tp.input_shapes.front().second.size(); i++) {
89+
result << "{";
90+
for (size_t j = 0lu; j < tp.input_shapes.size(); j++) {
91+
result << ov::test::utils::vec2str(tp.input_shapes[j].second[i])
92+
<< (j < tp.input_shapes.size() - 1lu ? "_" : "");
93+
}
94+
result << "}_";
95+
}
96+
result << "numRois=" << tp.num_rois << "_";
97+
result << "pooledH=" << tp.pooled_h << "_";
98+
result << "pooledW=" << tp.pooled_w << "_";
99+
result << "samplingRatio=" << tp.sampliong_ratio << "_";
100+
result << "spatialScale=" << tp.spatial_scale << "_";
101+
result << "clockwiseMode=" << tp.clockwise_mode << "_";
102+
result << "modelType=" << tp.model_type.to_string() << "_";
103+
result << "trgDev=" << tp.target_device;
104+
return result.str();
105+
}
106+
107+
void ROIAlignRotatedLayerTest::SetUp() {
108+
const TestParams tp = ExtractTestParams(this->GetParam());
109+
targetDevice = tp.target_device;
110+
init_input_shapes(tp.input_shapes);
111+
112+
const auto input_batch_size = inputDynamicShapes[0][0].get_length();
113+
const auto input_height = inputDynamicShapes[0][2].get_length();
114+
const auto input_width = inputDynamicShapes[0][3].get_length();
115+
116+
auto input = std::make_shared<ov::op::v0::Parameter>(tp.model_type, inputDynamicShapes[0]);
117+
const auto rois_shape = ov::Shape{static_cast<size_t>(tp.num_rois), ROI_DEF_SIZE};
118+
const auto rois_idx_shape = ov::Shape{static_cast<size_t>(tp.num_rois)};
119+
120+
auto rois = std::make_shared<ov::op::v0::Constant>(tp.model_type,
121+
rois_shape,
122+
FillRoisTensor(tp.num_rois, input_height, input_width).data());
123+
auto rois_idx = std::make_shared<ov::op::v0::Constant>(ov::element::i32,
124+
rois_idx_shape,
125+
FillBAtchIdxTensor(tp.num_rois, input_batch_size).data());
126+
auto roi_align = std::make_shared<ov::op::v15::ROIAlignRotated>(input,
127+
rois,
128+
rois_idx,
129+
tp.pooled_h,
130+
tp.pooled_w,
131+
tp.sampliong_ratio,
132+
tp.spatial_scale,
133+
tp.clockwise_mode);
134+
function = std::make_shared<ov::Model>(roi_align->outputs(), ov::ParameterVector{input}, "roi_align_rotated");
135+
}
136+
137+
} // namespace test
138+
} // namespace ov

src/tests/test_utils/unit_test_utils/tests_data/roi_align_rotated_data.h

+22
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,28 @@ TEST_DATA(LIST(1, 1, 5, 5),
287287
LIST(0),
288288
LIST(5.1271, 1.2473, 6.1773, 2.9598, 7.2275, 3.2300, 8.2777, 3.7458, 9.3279, 4.4060),
289289
"roi_align_rotated_all_features");
290+
TEST_DATA(LIST(1, 1, 2, 5),
291+
2,
292+
2,
293+
1.0f,
294+
2,
295+
true,
296+
LIST(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
297+
LIST(0.5, 0.5, 1, 1, 0),
298+
LIST(0),
299+
LIST(1.0, 1.25, 2.25, 2.50),
300+
"input_image_not_rectangular");
301+
TEST_DATA(LIST(2, 1, 2, 5),
302+
2,
303+
2,
304+
1.0f,
305+
2,
306+
true,
307+
LIST(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20),
308+
LIST(0.5, 1., 2., 5., 0.5, 0., 2., 5., 1., 0.),
309+
LIST(0, 1),
310+
LIST(0.5201, 1.9866, 2.5219, 3.0896, 0.0000, 16.7500, 0.0000, 16.7500),
311+
"input_image_not_rectangular_batch_2");
290312

291313
#undef PI
292314
#undef LIST

0 commit comments

Comments
 (0)