Skip to content

Commit

Permalink
[GPU][ROIAlignRotated]: Fixed a bug with wrong batch indexing and add…
Browse files Browse the repository at this point in the history
…ed 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)*
  • Loading branch information
pkowalc1 committed May 29, 2024
1 parent 6a8079b commit 5c0f38f
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/plugins/intel_gpu/src/plugin/ops/constant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -221,7 +222,8 @@ static void CreateConstantOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v0
if (constDims.size() == 4 && input_shape.size() == 3) { // In case of weight dim 4 and input dim 3,
constDims.push_back(1); // The weight cldnn tensor adds 1d to the end as the input cldnn tensor does
}
} else if (ov::is_type<ov::op::v3::ROIAlign>(outOp) || ov::is_type<ov::op::v9::ROIAlign>(outOp)) {
} else if (ov::is_type<ov::op::v3::ROIAlign>(outOp) || ov::is_type<ov::op::v9::ROIAlign>(outOp) ||
ov::is_type<ov::op::v15::ROIAlignRotated>(outOp)) { //< Hacks...
consts[op].needsBatchInterpretation = constDims.size() == 1;
} else if ((ov::is_type<ov::op::v5::Loop>(outOp) || ov::is_type<ov::op::v0::TensorIterator>(outOp))) {
// when inner network has 1d parameter which is connected to outer loop's constant 1d data,
Expand Down
Original file line number Diff line number Diff line change
@@ -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<ov::element::Type> 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<std::vector<ov::Shape>>{{{3, 8, 16, 16}},
{{2, 1, 16, 10}},
{{4, 3, 5, 12}}})),
::testing::ValuesIn(std::vector<int>{2, 4}),
::testing::Values(2),
::testing::Values(2),
::testing::Values(2),
::testing::ValuesIn(std::vector<float>{1, 0.625}),
::testing::ValuesIn(std::vector<bool>{true, false}),
::testing::ValuesIn(netPRCs),
::testing::Values(ov::test::utils::DEVICE_GPU)),
ROIAlignRotatedLayerTest::getTestCaseName);

} // namespace
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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<std::vector<InputShape>, // 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<roialignrotatedParams>,
virtual public ov::test::SubgraphBaseTest {
public:
static std::string getTestCaseName(const testing::TestParamInfo<roialignrotatedParams>& obj);

protected:
void SetUp() override;
};
} // namespace test
} // namespace ov
Original file line number Diff line number Diff line change
@@ -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 <random>

#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<InputShape> 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<float> dis(low, high);
return dis(engine);
}

static std::vector<float> FillRoisTensor(int num_rois, int height, int width) {
std::vector<float> 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<int> FillBAtchIdxTensor(int num_rois, int batch_size) {
std::vector<int> 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<roialignrotatedParams>& 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<ov::op::v0::Parameter>(tp.model_type, inputDynamicShapes[0]);
const auto rois_shape = ov::Shape{static_cast<size_t>(tp.num_rois), ROI_DEF_SIZE};
const auto rois_idx_shape = ov::Shape{static_cast<size_t>(tp.num_rois)};

auto rois = std::make_shared<ov::op::v0::Constant>(tp.model_type,
rois_shape,
FillRoisTensor(tp.num_rois, input_height, input_width).data());
auto rois_idx = std::make_shared<ov::op::v0::Constant>(ov::element::i32,
rois_idx_shape,
FillBAtchIdxTensor(tp.num_rois, input_batch_size).data());
auto roi_align = std::make_shared<ov::op::v15::ROIAlignRotated>(input,
rois,
rois_idx,
tp.pooled_h,
tp.pooled_w,
tp.sampliong_ratio,
tp.spatial_scale,
tp.clockwise_mode);
function = std::make_shared<ov::Model>(roi_align->outputs(), ov::ParameterVector{input}, "roi_align_rotated");
}

} // namespace test
} // namespace ov
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 5c0f38f

Please sign in to comment.