Liubo/roi align 9 ov core cpu plugin (#11188)

* roi_align_9: ov_core, transformations, template_plugin

* roi_align_9: CPU Plugin

* keep only constructor with enums which is aligned with spec

* remove evaluate function for ROIAlign_9

* Add op check test for operation ROIAlign-9

* Apply suggestions from code review

* fix version name from 'v0' to 'v3' in transform part

* use common shape_infer function for v3 and v9

* remove'tf_' prefix for ROIAlign::AlignedMode to avoid misleading for models from different platforms
This commit is contained in:
Bo Liu authored and GitHub committed 2022-05-10 08:14:37 +08:00
1 parent ad61593aa5
commit eddd31f58f
26 files changed
+1022 -35

No files matched your search

+1 -1
View File
@@ -58,7 +58,7 @@
* **Description**: *aligned_mode* specifies how to transform the coordinate in original tensor to the resized tensor.
* **Range of values**: name of the transformation mode in string format (here spatial_scale is resized_shape[x] / original_shape[x], resized_shape[x] is the shape of resized tensor in axis x, original_shape[x] is the shape of original tensor in axis x and x_original is a coordinate in axis x, for any axis x from the input axes):
* *asymmetric* - the coordinate in the resized tensor axis x is calculated according to the formula x_original * spatial_scale
* *tf_half_pixel_for_nn* - the coordinate in the resized tensor axis x is x_original * spatial_scale - 0.5
* *half_pixel_for_nn* - the coordinate in the resized tensor axis x is x_original * spatial_scale - 0.5
* *half_pixel* - the coordinate in the resized tensor axis x is calculated as ((x_original + 0.5) * spatial_scale) - 0.5
* **Type**: string
* **Default value**: asymmetric
@@ -69,6 +69,7 @@
#include <ngraph/runtime/reference/reorg_yolo.hpp>
#include <ngraph/runtime/reference/reverse_sequence.hpp>
#include <ngraph/runtime/reference/rnn_cell.hpp>
#include <ngraph/runtime/reference/roi_align.hpp>
#include <ngraph/runtime/reference/roi_pooling.hpp>
#include <ngraph/runtime/reference/roll.hpp>
#include <ngraph/runtime/reference/scatter_nd_update.hpp>
@@ -3084,6 +3085,40 @@ bool evaluate(const shared_ptr<op::v5::GRUSequence>& op,
return true;
}
template <element::Type_t ET>
bool evaluate(const shared_ptr<op::v9::ROIAlign>& op, const HostTensorVector& outputs, const HostTensorVector& inputs) {
using T = typename element_type_traits<ET>::value_type;
std::vector<int64_t> batch_indices_vec_scaled_up = host_tensor_2_vector<int64_t>(inputs[2]);
op::v3::ROIAlign::PoolingMode m_mode_v3;
switch (op->get_mode()) {
case op::v9::ROIAlign::PoolingMode::AVG: {
m_mode_v3 = op::v3::ROIAlign::PoolingMode::AVG;
break;
}
case op::v9::ROIAlign::PoolingMode::MAX: {
m_mode_v3 = op::v3::ROIAlign::PoolingMode::MAX;
break;
}
default: {
NGRAPH_CHECK(false, "unsupported PoolingMode ");
}
}
runtime::reference::roi_align<T>(inputs[0]->get_data_ptr<const T>(),
inputs[1]->get_data_ptr<const T>(),
batch_indices_vec_scaled_up.data(),
outputs[0]->get_data_ptr<T>(),
op->get_input_shape(0),
op->get_input_shape(1),
op->get_input_shape(2),
op->get_output_shape(0),
op->get_pooled_h(),
op->get_pooled_w(),
op->get_sampling_ratio(),
op->get_spatial_scale(),
m_mode_v3,
op->get_aligned_mode());
return true;
}
template <element::Type_t ET>
bool evaluate(const shared_ptr<op::v0::ROIPooling>& op,
const HostTensorVector& outputs,
const HostTensorVector& inputs) {
@@ -132,3 +132,4 @@ NGRAPH_OP(PriorBox, ngraph::op::v8)
NGRAPH_OP(PRelu, op::v0)
NGRAPH_OP(RDFT, op::v9)
NGRAPH_OP(ROIAlign, op::v9)
@@ -4,6 +4,7 @@
#include <gtest/gtest.h>
#include "openvino/opsets/opset9.hpp"
#include "openvino/opsets/opset5.hpp"
#include "openvino/opsets/opset4.hpp"
#include "openvino/opsets/opset3.hpp"
@@ -49,6 +50,43 @@ struct ROIAlignParams {
std::string testcaseName;
};
struct ROIAlignV9Params {
template <class IT>
ROIAlignV9Params(const PartialShape& pShape, const element::Type& iType, const std::vector<IT>& iValues,
const reference_tests::Tensor& expectedFeatureMap,
const reference_tests::Tensor& coords, const reference_tests::Tensor& roiIdx,
const int32_t pooledH, const int32_t pooledW,
const float spatialScale, const int32_t poolingRatio, const std::string& poolingMode,
const std::string& alignedMode, const std::string& testcaseName)
: pShape(pShape),
iType(iType),
featureMap(CreateTensor(iType, iValues)),
expectedFeatureMap(expectedFeatureMap),
coords(coords),
roiIdx(roiIdx),
pooledH(pooledH),
pooledW(pooledW),
spatialScale(spatialScale),
poolingRatio(poolingRatio),
poolingMode(poolingMode),
alignedMode(alignedMode),
testcaseName(testcaseName) {}
PartialShape pShape;
element::Type iType;
ov::Tensor featureMap;
reference_tests::Tensor expectedFeatureMap;
reference_tests::Tensor coords;
reference_tests::Tensor roiIdx;
int32_t pooledH;
int32_t pooledW;
float spatialScale;
int32_t poolingRatio;
std::string poolingMode;
std::string alignedMode;
std::string testcaseName;
};
class ReferenceROIAlignTest : public testing::TestWithParam<ROIAlignParams>, public CommonReferenceTest {
public:
void SetUp() override {
@@ -98,10 +136,67 @@ private:
}
};
class ReferenceROIAlignV9Test : public testing::TestWithParam<ROIAlignV9Params>, public CommonReferenceTest {
public:
void SetUp() override {
auto params = GetParam();
function = CreateFunction(params);
inputData = {params.featureMap};
refOutData = {params.expectedFeatureMap.data};
}
static std::string getTestCaseName(const testing::TestParamInfo<ROIAlignV9Params>& obj) {
auto param = obj.param;
std::ostringstream result;
result << "iType=" << param.iType;
result << "_pShape=" << param.pShape;
result << "_efType=" << param.expectedFeatureMap.type;
result << "_efShape=" << param.expectedFeatureMap.shape;
result << "_cType=" << param.coords.type;
result << "_cShape=" << param.coords.shape;
result << "_rType=" << param.roiIdx.type;
result << "_rShape=" << param.roiIdx.shape;
result << "_pooledH=" << param.pooledH;
result << "_pooledW=" << param.pooledW;
result << "_spatialScale=" << param.spatialScale;
result << "_poolingRatio=" << param.poolingRatio;
result << "_poolingMode=" << param.poolingMode;
result << "_alignedMode=" << param.alignedMode;
if (param.testcaseName != "") {
result << "_=" << param.testcaseName;
}
return result.str();
}
private:
static std::shared_ptr<Model> CreateFunction(const ROIAlignV9Params& params) {
const auto featureMap = std::make_shared<opset1::Parameter>(params.iType, params.pShape);
const auto coords = std::make_shared<opset1::Constant>(params.coords.type, params.coords.shape, params.coords.data.data());
const auto roisIdx = std::make_shared<opset1::Constant>(params.roiIdx.type, params.roiIdx.shape, params.roiIdx.data.data());
const auto pooling_mode = EnumNames<opset9::ROIAlign::PoolingMode>::as_enum(params.poolingMode);
const auto aligned_mode = EnumNames<opset9::ROIAlign::AlignedMode>::as_enum(params.alignedMode);
const auto roi_align = std::make_shared<opset9::ROIAlign>(featureMap,
coords,
roisIdx,
params.pooledH,
params.pooledW,
params.poolingRatio,
params.spatialScale,
pooling_mode,
aligned_mode);
auto f = std::make_shared<Model>(NodeVector{roi_align}, ParameterVector{featureMap});
return f;
}
};
TEST_P(ReferenceROIAlignTest, CompareWithRefs) {
Exec();
}
TEST_P(ReferenceROIAlignV9Test, CompareWithRefs) {
Exec();
}
template <element::Type_t ET, element::Type_t ET_IND>
std::vector<ROIAlignParams> generateParams() {
using T = typename element_type_traits<ET>::value_type;
@@ -173,6 +268,94 @@ std::vector<ROIAlignParams> generateCombinedParams() {
return combinedParams;
}
template <element::Type_t ET, element::Type_t ET_IND>
std::vector<ROIAlignV9Params> generateParamsV9() {
using T = typename element_type_traits<ET>::value_type;
using T_IND = typename element_type_traits<ET_IND>::value_type;
std::vector<ROIAlignV9Params> params {
ROIAlignV9Params(PartialShape{2, 1, 8, 8}, ET,
std::vector<T>{0, 1, 8, 5, 5, 2, 0, 7, 7, 10, 4, 5, 9, 0, 0, 5,
7, 0, 4, 0, 4, 7, 6, 10, 9, 5, 1, 7, 4, 7, 10, 8,
2, 0, 8, 3, 6, 8, 10, 4, 2, 10, 7, 8, 7, 0, 6, 9,
2, 4, 8, 5, 2, 3, 3, 1, 5, 9, 10, 0, 9, 5, 5, 3,
10, 5, 2, 0, 10, 0, 5, 4, 3, 10, 5, 5, 10, 0, 8, 8,
9, 1, 0, 7, 9, 6, 8, 7, 10, 9, 2, 3, 3, 5, 6, 9,
4, 9, 2, 4, 5, 5, 3, 1, 1, 6, 8, 0, 5, 5, 10, 8,
6, 9, 6, 9, 1, 2, 7, 1, 1, 3, 0, 4, 0, 7, 10, 2},
reference_tests::Tensor(ET, {2, 1, 2, 2}, std::vector<T>{3, 3.75, 4.75, 5, 3, 5.5, 2.75, 3.75}),
reference_tests::Tensor(ET, {2, 4}, std::vector<T>{2, 2, 4, 4, 2, 2, 4, 4}),
reference_tests::Tensor(ET_IND, {2}, std::vector<T_IND>{0, 1}),
2, 2, 1, 2, "avg", "asymmetric", "roi_align_v9_avg_asymmetric"),
ROIAlignV9Params(PartialShape{2, 1, 8, 8}, ET,
std::vector<T>{0, 1, 8, 5, 5, 2, 0, 7, 7, 10, 4, 5, 9, 0, 0, 5,
7, 0, 4, 0, 4, 7, 6, 10, 9, 5, 1, 7, 4, 7, 10, 8,
2, 0, 8, 3, 6, 8, 10, 4, 2, 10, 7, 8, 7, 0, 6, 9,
2, 4, 8, 5, 2, 3, 3, 1, 5, 9, 10, 0, 9, 5, 5, 3,
10, 5, 2, 0, 10, 0, 5, 4, 3, 10, 5, 5, 10, 0, 8, 8,
9, 1, 0, 7, 9, 6, 8, 7, 10, 9, 2, 3, 3, 5, 6, 9,
4, 9, 2, 4, 5, 5, 3, 1, 1, 6, 8, 0, 5, 5, 10, 8,
6, 9, 6, 9, 1, 2, 7, 1, 1, 3, 0, 4, 0, 7, 10, 2},
reference_tests::Tensor(ET, {2, 1, 2, 2}, std::vector<T>{3.14, 2.16, 2.86, 5.03, 1.83, 5.84, 2.77, 3.44}),
reference_tests::Tensor(ET, {2, 4}, std::vector<T>{2, 2, 4, 4, 2, 2, 4, 4}),
reference_tests::Tensor(ET_IND, {2}, std::vector<T_IND>{0, 1}),
2, 2, 1, 2, "avg", "half_pixel_for_nn", "roi_align_v9_avg_half_pixel_for_nn"),
ROIAlignV9Params(PartialShape{2, 1, 8, 8}, ET,
std::vector<T>{0, 1, 8, 5, 5, 2, 0, 7, 7, 10, 4, 5, 9, 0, 0, 5,
7, 0, 4, 0, 4, 7, 6, 10, 9, 5, 1, 7, 4, 7, 10, 8,
2, 0, 8, 3, 6, 8, 10, 4, 2, 10, 7, 8, 7, 0, 6, 9,
2, 4, 8, 5, 2, 3, 3, 1, 5, 9, 10, 0, 9, 5, 5, 3,
10, 5, 2, 0, 10, 0, 5, 4, 3, 10, 5, 5, 10, 0, 8, 8,
9, 1, 0, 7, 9, 6, 8, 7, 10, 9, 2, 3, 3, 5, 6, 9,
4, 9, 2, 4, 5, 5, 3, 1, 1, 6, 8, 0, 5, 5, 10, 8,
6, 9, 6, 9, 1, 2, 7, 1, 1, 3, 0, 4, 0, 7, 10, 2},
reference_tests::Tensor(ET, {2, 1, 2, 2}, std::vector<T>{4.375, 4.9375, 5.6875, 5.625, 4.625, 7.125, 3.3125, 4.3125}),
reference_tests::Tensor(ET, {2, 4}, std::vector<T>{2, 2, 4, 4, 2, 2, 4, 4}),
reference_tests::Tensor(ET_IND, {2}, std::vector<T_IND>{0, 1}),
2, 2, 1, 2, "max", "half_pixel", "roi_align_v9_max_half_pixel"),
};
return params;
}
std::vector<ROIAlignV9Params> generateCombinedParamsV9() {
const std::vector<std::vector<ROIAlignV9Params>> generatedParams {
generateParamsV9<element::Type_t::bf16, element::Type_t::i8>(),
generateParamsV9<element::Type_t::f16, element::Type_t::i8>(),
generateParamsV9<element::Type_t::f32, element::Type_t::i8>(),
generateParamsV9<element::Type_t::bf16, element::Type_t::i16>(),
generateParamsV9<element::Type_t::f16, element::Type_t::i16>(),
generateParamsV9<element::Type_t::f32, element::Type_t::i16>(),
generateParamsV9<element::Type_t::bf16, element::Type_t::i32>(),
generateParamsV9<element::Type_t::f16, element::Type_t::i32>(),
generateParamsV9<element::Type_t::f32, element::Type_t::i32>(),
generateParamsV9<element::Type_t::bf16, element::Type_t::i64>(),
generateParamsV9<element::Type_t::f16, element::Type_t::i64>(),
generateParamsV9<element::Type_t::f32, element::Type_t::i64>(),
generateParamsV9<element::Type_t::bf16, element::Type_t::u8>(),
generateParamsV9<element::Type_t::f16, element::Type_t::u8>(),
generateParamsV9<element::Type_t::f32, element::Type_t::u8>(),
generateParamsV9<element::Type_t::bf16, element::Type_t::u16>(),
generateParamsV9<element::Type_t::f16, element::Type_t::u16>(),
generateParamsV9<element::Type_t::f32, element::Type_t::u16>(),
generateParamsV9<element::Type_t::bf16, element::Type_t::u32>(),
generateParamsV9<element::Type_t::f16, element::Type_t::u32>(),
generateParamsV9<element::Type_t::f32, element::Type_t::u32>(),
generateParamsV9<element::Type_t::bf16, element::Type_t::u64>(),
generateParamsV9<element::Type_t::f16, element::Type_t::u64>(),
generateParamsV9<element::Type_t::f32, element::Type_t::u64>(),
};
std::vector<ROIAlignV9Params> combinedParams;
for (const auto& params : generatedParams) {
combinedParams.insert(combinedParams.end(), params.begin(), params.end());
}
return combinedParams;
}
INSTANTIATE_TEST_SUITE_P(smoke_ROIAlign_With_Hardcoded_Refs, ReferenceROIAlignTest,
testing::ValuesIn(generateCombinedParams()), ReferenceROIAlignTest::getTestCaseName);
} // namespace
INSTANTIATE_TEST_SUITE_P(smoke_ROIAlignV9_With_Hardcoded_Refs, ReferenceROIAlignV9Test,
testing::ValuesIn(generateCombinedParamsV9()), ReferenceROIAlignV9Test::getTestCaseName);
} // namespace
@@ -0,0 +1,26 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/pass/graph_rewrite.hpp>
#include <transformations_visibility.hpp>
namespace ngraph {
namespace pass {
class TRANSFORMATIONS_API ConvertROIAlign3To9;
} // namespace pass
} // namespace ngraph
/**
* @ingroup ie_transformation_common_api
* @brief ConvertROIAlign3To9 converts v3::ROIAlign into v9::ROIAlign.
*/
class ngraph::pass::ConvertROIAlign3To9 : public ngraph::pass::MatcherPass {
public:
OPENVINO_RTTI("ConvertROIAlign3To9", "0");
ConvertROIAlign3To9();
};
@@ -0,0 +1,26 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/pass/graph_rewrite.hpp>
#include <transformations_visibility.hpp>
namespace ngraph {
namespace pass {
class TRANSFORMATIONS_API ConvertROIAlign9To3;
} // namespace pass
} // namespace ngraph
/**
* @ingroup ie_transformation_common_api
* @brief ConvertROIAlign9To3 converts v9::ROIAlign into v3::ROIAlign.
*/
class ngraph::pass::ConvertROIAlign9To3 : public ngraph::pass::MatcherPass {
public:
OPENVINO_RTTI("ConvertROIAlign9To3", "0");
ConvertROIAlign9To3();
};
@@ -84,6 +84,8 @@
#include "transformations/op_conversions/convert_pad_to_group_conv.hpp"
#include "transformations/op_conversions/convert_prior_box_v8_to_v0.hpp"
#include "transformations/op_conversions/convert_reduce_to_pooling.hpp"
#include "transformations/op_conversions/convert_roi_align_v3_to_v9.hpp"
#include "transformations/op_conversions/convert_roi_align_v9_to_v3.hpp"
#include "transformations/op_conversions/convert_scatter_elements_to_scatter.hpp"
#include "transformations/op_conversions/convert_softmax_downgrade.hpp"
#include "transformations/op_conversions/convert_softmax_upgrade.hpp"
@@ -197,6 +199,8 @@ bool ngraph::pass::CommonOptimizations::run_on_model(const std::shared_ptr<ngrap
manager.register_pass<ngraph::pass::ConvertPriorBox8To0>(); // not plugins implemented priorbox8
manager.register_pass<ngraph::pass::ConvertDetectionOutput1ToDetectionOutput8, false>();
manager.register_pass<ngraph::pass::ConvertDetectionOutput8ToDetectionOutput1>();
manager.register_pass<ngraph::pass::ConvertROIAlign3To9, false>();
manager.register_pass<ngraph::pass::ConvertROIAlign9To3>();
auto fq_fusions = manager.register_pass<ngraph::pass::GraphRewrite>();
fq_fusions->add_matcher<ngraph::pass::FakeQuantizeMulFusion>();
@@ -0,0 +1,61 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/op_conversions/convert_roi_align_v3_to_v9.hpp"
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/opsets/opset9.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/rt_info.hpp>
#include "itt.hpp"
ngraph::pass::ConvertROIAlign3To9::ConvertROIAlign3To9() {
MATCHER_SCOPE(ConvertROIAlign3To9);
auto roi_align_v3 = pattern::wrap_type<ngraph::opset3::ROIAlign>();
ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) {
auto roi_align_v3_node = std::dynamic_pointer_cast<ngraph::opset3::ROIAlign>(m.get_match_root());
if (!roi_align_v3_node)
return false;
const int pooled_h = roi_align_v3_node->get_pooled_h();
const int pooled_w = roi_align_v3_node->get_pooled_w();
const int sampling_ratio = roi_align_v3_node->get_sampling_ratio();
const float spatial_scale = roi_align_v3_node->get_spatial_scale();
ngraph::opset3::ROIAlign::PoolingMode m_mode_v3 = roi_align_v3_node->get_mode();
ngraph::opset9::ROIAlign::PoolingMode m_mode_v9;
switch (m_mode_v3) {
case ngraph::opset3::ROIAlign::PoolingMode::AVG: {
m_mode_v9 = ngraph::opset9::ROIAlign::PoolingMode::AVG;
break;
}
case ngraph::opset3::ROIAlign::PoolingMode::MAX: {
m_mode_v9 = ngraph::opset9::ROIAlign::PoolingMode::MAX;
break;
}
default: {
throw ngraph_error("unsupported PoolingMode ");
}
}
auto roi_align_v9 = std::make_shared<ngraph::opset9::ROIAlign>(roi_align_v3_node->input_value(0),
roi_align_v3_node->input_value(1),
roi_align_v3_node->input_value(2),
pooled_h,
pooled_w,
sampling_ratio,
spatial_scale,
m_mode_v9);
roi_align_v9->set_friendly_name(roi_align_v3_node->get_friendly_name());
ngraph::copy_runtime_info(roi_align_v3_node, roi_align_v9);
ngraph::replace_node(roi_align_v3_node, roi_align_v9);
return true;
};
auto m = std::make_shared<pattern::Matcher>(roi_align_v3, matcher_name);
register_matcher(m, callback);
}
@@ -0,0 +1,65 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/op_conversions/convert_roi_align_v9_to_v3.hpp"
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/opsets/opset9.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/rt_info.hpp>
#include "itt.hpp"
ngraph::pass::ConvertROIAlign9To3::ConvertROIAlign9To3() {
MATCHER_SCOPE(ConvertROIAlign9To3);
auto roi_align_v9 = pattern::wrap_type<ngraph::opset9::ROIAlign>();
ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) {
auto roi_align_v9_node = std::dynamic_pointer_cast<ngraph::opset9::ROIAlign>(m.get_match_root());
if (!roi_align_v9_node)
return false;
ngraph::opset9::ROIAlign::AlignedMode aligned_mode_v9 = roi_align_v9_node->get_aligned_mode();
if (aligned_mode_v9 != ngraph::opset9::ROIAlign::AlignedMode::ASYMMETRIC)
return false;
const int pooled_h = roi_align_v9_node->get_pooled_h();
const int pooled_w = roi_align_v9_node->get_pooled_w();
const int sampling_ratio = roi_align_v9_node->get_sampling_ratio();
const float spatial_scale = roi_align_v9_node->get_spatial_scale();
ngraph::opset9::ROIAlign::PoolingMode m_mode_v9 = roi_align_v9_node->get_mode();
ngraph::opset3::ROIAlign::PoolingMode m_mode_v3;
switch (m_mode_v9) {
case ngraph::opset9::ROIAlign::PoolingMode::AVG: {
m_mode_v3 = ngraph::opset3::ROIAlign::PoolingMode::AVG;
break;
}
case ngraph::opset9::ROIAlign::PoolingMode::MAX: {
m_mode_v3 = ngraph::opset3::ROIAlign::PoolingMode::MAX;
break;
}
default: {
throw ngraph_error("unsupported PoolingMode ");
}
}
auto roi_align_v3 = std::make_shared<ngraph::opset3::ROIAlign>(roi_align_v9_node->input_value(0),
roi_align_v9_node->input_value(1),
roi_align_v9_node->input_value(2),
pooled_h,
pooled_w,
sampling_ratio,
spatial_scale,
m_mode_v3);
roi_align_v3->set_friendly_name(roi_align_v9_node->get_friendly_name());
ngraph::copy_runtime_info(roi_align_v9_node, roi_align_v3);
ngraph::replace_node(roi_align_v9_node, roi_align_v3);
return true;
};
auto m = std::make_shared<pattern::Matcher>(roi_align_v9, matcher_name);
register_matcher(m, callback);
}
+3
View File
@@ -12,6 +12,9 @@ namespace op {
namespace v3 {
using ov::op::v3::ROIAlign;
} // namespace v3
namespace v9 {
using ov::op::v9::ROIAlign;
} // namespace v9
using v3::ROIAlign;
} // namespace op
} // namespace ngraph
@@ -84,6 +84,71 @@ private:
PoolingMode m_mode;
};
} // namespace v3
namespace v9 {
class OPENVINO_API ROIAlign : public Op {
public:
OPENVINO_OP("ROIAlign", "opset9");
enum class PoolingMode { AVG, MAX };
enum class AlignedMode { ASYMMETRIC, HALF_PIXEL_FOR_NN, HALF_PIXEL };
ROIAlign() = default;
/// \brief Constructs a ROIAlign operation.
///
/// \param input Input feature map {N, C, H, W}
/// \param rois Regions of interest to pool over
/// \param batch_indices Indices of images in the batch matching
/// the number or ROIs
/// \param pooled_h Height of the ROI output features
/// \param pooled_w Width of the ROI output features
/// \param sampling_ratio Number of sampling points used to compute
/// an output element
/// \param spatial_scale Spatial scale factor used to translate ROI coordinates
/// \param mode Method of pooling - 'avg' or 'max'
/// \param aligned_mode Method of coordinates alignment - 'asymmetric', 'half_pixel_for_nn' or 'half_pixel'
ROIAlign(const Output<Node>& input,
const Output<Node>& rois,
const Output<Node>& batch_indices,
const int pooled_h,
const int pooled_w,
const int sampling_ratio,
const float spatial_scale,
const PoolingMode mode,
const AlignedMode aligned_mode = AlignedMode::ASYMMETRIC);
void validate_and_infer_types() override;
bool visit_attributes(AttributeVisitor& visitor) override;
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
int get_pooled_h() const {
return m_pooled_h;
}
int get_pooled_w() const {
return m_pooled_w;
}
int get_sampling_ratio() const {
return m_sampling_ratio;
}
float get_spatial_scale() const {
return m_spatial_scale;
}
PoolingMode get_mode() const {
return m_mode;
}
AlignedMode get_aligned_mode() const {
return m_aligned_mode;
}
private:
PoolingMode mode_from_string(const std::string& mode) const;
int m_pooled_h;
int m_pooled_w;
int m_sampling_ratio;
float m_spatial_scale;
PoolingMode m_mode;
AlignedMode m_aligned_mode;
};
} // namespace v9
} // namespace op
std::ostream& operator<<(std::ostream& s, const op::v3::ROIAlign::PoolingMode& mode);
@@ -99,4 +164,28 @@ public:
BWDCMP_RTTI_DECLARATION;
};
std::ostream& operator<<(std::ostream& s, const op::v9::ROIAlign::PoolingMode& mode);
template <>
class OPENVINO_API AttributeAdapter<op::v9::ROIAlign::PoolingMode>
: public EnumAttributeAdapterBase<op::v9::ROIAlign::PoolingMode> {
public:
AttributeAdapter(op::v9::ROIAlign::PoolingMode& value)
: EnumAttributeAdapterBase<op::v9::ROIAlign::PoolingMode>(value) {}
OPENVINO_RTTI("AttributeAdapter<ov::op::v9::ROIAlign::PoolingMode>");
};
std::ostream& operator<<(std::ostream& s, const op::v9::ROIAlign::AlignedMode& mode);
template <>
class OPENVINO_API AttributeAdapter<op::v9::ROIAlign::AlignedMode>
: public EnumAttributeAdapterBase<op::v9::ROIAlign::AlignedMode> {
public:
AttributeAdapter(op::v9::ROIAlign::AlignedMode& value)
: EnumAttributeAdapterBase<op::v9::ROIAlign::AlignedMode>(value) {}
OPENVINO_RTTI("AttributeAdapter<ov::op::v9::ROIAlign::AlignedMode>");
};
} // namespace ov
@@ -120,7 +120,6 @@ _OPENVINO_OP_REG(EmbeddingBagOffsetsSum, ov::op::v3)
_OPENVINO_OP_REG(GRUCell, ov::op::v3)
_OPENVINO_OP_REG(NonZero, ov::op::v3)
_OPENVINO_OP_REG(RNNCell, ov::op::v0)
_OPENVINO_OP_REG(ROIAlign, ov::op::v3)
_OPENVINO_OP_REG(ScatterElementsUpdate, ov::op::v3)
_OPENVINO_OP_REG(ScatterUpdate, ov::op::v3)
_OPENVINO_OP_REG(ShuffleChannels, ov::op::v0)
@@ -193,3 +192,4 @@ _OPENVINO_OP_REG(PriorBox, ov::op::v8)
_OPENVINO_OP_REG(IRDFT, ov::op::v9)
_OPENVINO_OP_REG(RDFT, ov::op::v9)
_OPENVINO_OP_REG(Eye, ov::op::v9)
_OPENVINO_OP_REG(ROIAlign, ov::op::v9)
@@ -13,6 +13,7 @@ namespace ngraph {
namespace runtime {
namespace reference {
using ROIPoolingMode = op::v3::ROIAlign::PoolingMode;
using AlignedMode = op::v9::ROIAlign::AlignedMode;
template <typename T>
void roi_align(const T* feature_maps,
const T* rois,
@@ -26,7 +27,8 @@ void roi_align(const T* feature_maps,
const int pooled_width,
const int sampling_ratio,
const float spatial_scale,
const ROIPoolingMode& pooling_mode) {
const ROIPoolingMode& pooling_mode,
const AlignedMode& aligned_mode = AlignedMode::ASYMMETRIC) {
auto C = feature_maps_shape[1];
auto feature_map_height = feature_maps_shape[2];
auto feature_map_width = feature_maps_shape[3];
@@ -37,15 +39,44 @@ void roi_align(const T* feature_maps,
CoordinateTransform rois_transform(rois_shape);
CoordinateTransform out_transform(out_shape);
bool aligned = false;
T offset_src = static_cast<T>(0);
T offset_dst = static_cast<T>(0);
switch (aligned_mode) {
case AlignedMode::HALF_PIXEL_FOR_NN: {
aligned = true;
offset_dst = static_cast<T>(-0.5);
break;
}
case AlignedMode::HALF_PIXEL: {
aligned = true;
offset_src = static_cast<T>(0.5);
offset_dst = static_cast<T>(-0.5);
break;
}
case AlignedMode::ASYMMETRIC: {
break;
}
default: {
throw ngraph_error(std::string("Not supported aligned_mode"));
break;
}
}
for (unsigned int roi_index = 0; roi_index < num_rois; roi_index++) {
// Get ROI`s corners
T x1 = rois[rois_transform.index({roi_index, 0})] * spatial_scale;
T y1 = rois[rois_transform.index({roi_index, 1})] * spatial_scale;
T x2 = rois[rois_transform.index({roi_index, 2})] * spatial_scale;
T y2 = rois[rois_transform.index({roi_index, 3})] * spatial_scale;
T x1 = (rois[rois_transform.index({roi_index, 0})] + offset_src) * spatial_scale + offset_dst;
T y1 = (rois[rois_transform.index({roi_index, 1})] + offset_src) * spatial_scale + offset_dst;
T x2 = (rois[rois_transform.index({roi_index, 2})] + offset_src) * spatial_scale + offset_dst;
T y2 = (rois[rois_transform.index({roi_index, 3})] + offset_src) * spatial_scale + offset_dst;
T roi_width = std::max(x2 - x1, static_cast<T>(1.0));
T roi_height = std::max(y2 - y1, static_cast<T>(1.0));
T roi_width = x2 - x1;
T roi_height = y2 - y1;
if (!aligned) {
roi_width = std::max(roi_width, static_cast<T>(1.0));
roi_height = std::max(roi_height, static_cast<T>(1.0));
}
T bin_width = roi_width / pooled_width;
T bin_height = roi_height / pooled_height;
@@ -11,10 +11,11 @@
namespace ov {
namespace op {
namespace v3 {
template <class T>
void shape_infer(const ov::op::v3::ROIAlign* op, const std::vector<T>& input_shapes, std::vector<T>& output_shapes) {
using DimType = typename std::iterator_traits<typename T::iterator>::value_type;
template <class OpType, class ShapeType>
void infer_roi_align_shape(const OpType* op,
const std::vector<ShapeType>& input_shapes,
std::vector<ShapeType>& output_shapes) {
using DimType = typename std::iterator_traits<typename ShapeType::iterator>::value_type;
NODE_VALIDATION_CHECK(op, input_shapes.size() == 3 && output_shapes.size() == 1);
const auto& input_ps = input_shapes[0];
@@ -71,7 +72,23 @@ void shape_infer(const ov::op::v3::ROIAlign* op, const std::vector<T>& input_sha
output_shape[0] = Dimension::dynamic();
}
}
template <class T>
void shape_infer(const ov::op::v3::ROIAlign* op, const std::vector<T>& input_shapes, std::vector<T>& output_shapes) {
NODE_VALIDATION_CHECK(op, input_shapes.size() == 3 && output_shapes.size() == 1);
ov::op::v3::infer_roi_align_shape(op, input_shapes, output_shapes);
}
} // namespace v3
namespace v9 {
template <class T>
void shape_infer(const ov::op::v9::ROIAlign* op, const std::vector<T>& input_shapes, std::vector<T>& output_shapes) {
using DimType = typename std::iterator_traits<typename T::iterator>::value_type;
NODE_VALIDATION_CHECK(op, input_shapes.size() == 3 && output_shapes.size() == 1);
ov::op::v3::infer_roi_align_shape(op, input_shapes, output_shapes);
}
} // namespace v9
} // namespace op
} // namespace ov
+130 -6
View File
@@ -119,6 +119,98 @@ shared_ptr<Node> op::v3::ROIAlign::clone_with_new_inputs(const OutputVector& new
m_mode);
}
// ------------------------------ V9 ------------------------------
op::v9::ROIAlign::ROIAlign(const Output<Node>& input,
const Output<Node>& rois,
const Output<Node>& batch_indices,
const int pooled_h,
const int pooled_w,
const int sampling_ratio,
const float spatial_scale,
const PoolingMode mode,
const AlignedMode aligned_mode)
: Op{{input, rois, batch_indices}},
m_pooled_h{pooled_h},
m_pooled_w{pooled_w},
m_sampling_ratio{sampling_ratio},
m_spatial_scale{spatial_scale},
m_mode{mode},
m_aligned_mode{aligned_mode} {
constructor_validate_and_infer_types();
}
void op::v9::ROIAlign::validate_and_infer_types() {
NGRAPH_OP_SCOPE(v9_ROIAlign_validate_and_infer_types);
NODE_VALIDATION_CHECK(this,
get_input_element_type(0).is_real() && get_input_element_type(1).is_real(),
"The data type for input and ROIs is expected to be a floating point type. Got: ",
get_input_element_type(0),
" and: ",
get_input_element_type(1));
NODE_VALIDATION_CHECK(this,
get_input_element_type(0) == get_input_element_type(1),
"Type of feature maps (inputs) and rois is expected to be the same. Got: ",
get_input_element_type(0),
" and: ",
get_input_element_type(1));
NODE_VALIDATION_CHECK(this,
get_input_element_type(2).is_integral_number(),
"The data type for batch indices is expected to be an integer. Got: ",
get_input_element_type(2));
std::vector<ov::PartialShape> output_shapes = {ov::PartialShape{}};
const std::vector<ov::PartialShape> input_shapes = {get_input_partial_shape(0),
get_input_partial_shape(1),
get_input_partial_shape(2)};
shape_infer(this, input_shapes, output_shapes);
set_output_size(1);
set_output_type(0, get_input_element_type(0), output_shapes[0]);
const auto& input_ps = get_input_partial_shape(0);
// if the channels dimension is not known
// the first input should be used during the function specialization
if (input_ps.rank().is_static() && input_ps[1].is_dynamic()) {
set_input_is_relevant_to_shape(0);
}
// if the 'NUM_ROIS' value is not known
// the last 2 inputs should be used during the function specialization
if ((output_shapes[0])[0].is_dynamic()) {
set_input_is_relevant_to_shape(1);
set_input_is_relevant_to_shape(2);
}
}
bool op::v9::ROIAlign::visit_attributes(AttributeVisitor& visitor) {
NGRAPH_OP_SCOPE(v9_ROIAlign_visit_attributes);
visitor.on_attribute("pooled_h", m_pooled_h);
visitor.on_attribute("pooled_w", m_pooled_w);
visitor.on_attribute("sampling_ratio", m_sampling_ratio);
visitor.on_attribute("spatial_scale", m_spatial_scale);
visitor.on_attribute("mode", m_mode);
visitor.on_attribute("aligned_mode", m_aligned_mode);
return true;
}
shared_ptr<Node> op::v9::ROIAlign::clone_with_new_inputs(const OutputVector& new_args) const {
NGRAPH_OP_SCOPE(v9_ROIAlign_clone_with_new_inputs);
check_new_args_count(this, new_args);
return make_shared<ROIAlign>(new_args.at(0),
new_args.at(1),
new_args.at(2),
m_pooled_h,
m_pooled_w,
m_sampling_ratio,
m_spatial_scale,
m_mode,
m_aligned_mode);
}
namespace ov {
BWDCMP_RTTI_DEFINITION(AttributeAdapter<ov::op::v3::ROIAlign::PoolingMode>);
@@ -130,12 +222,38 @@ NGRAPH_API EnumNames<ngraph::op::v3::ROIAlign::PoolingMode>& EnumNames<ngraph::o
return enum_names;
}
template <>
NGRAPH_API EnumNames<ngraph::op::v9::ROIAlign::PoolingMode>& EnumNames<ngraph::op::v9::ROIAlign::PoolingMode>::get() {
static auto enum_names = EnumNames<ngraph::op::v9::ROIAlign::PoolingMode>(
"op::v9::ROIAlign::PoolingMode",
{{"avg", ngraph::op::v9::ROIAlign::PoolingMode::AVG}, {"max", ngraph::op::v9::ROIAlign::PoolingMode::MAX}});
return enum_names;
}
template <>
NGRAPH_API EnumNames<ngraph::op::v9::ROIAlign::AlignedMode>& EnumNames<ngraph::op::v9::ROIAlign::AlignedMode>::get() {
static auto enum_names = EnumNames<ngraph::op::v9::ROIAlign::AlignedMode>(
"op::v9::ROIAlign::AlignedMode",
{{"asymmetric", ngraph::op::v9::ROIAlign::AlignedMode::ASYMMETRIC},
{"half_pixel_for_nn", ngraph::op::v9::ROIAlign::AlignedMode::HALF_PIXEL_FOR_NN},
{"half_pixel", ngraph::op::v9::ROIAlign::AlignedMode::HALF_PIXEL}});
return enum_names;
}
} // namespace ov
std::ostream& ov::operator<<(std::ostream& s, const op::v3::ROIAlign::PoolingMode& type) {
return s << as_string(type);
}
std::ostream& ov::operator<<(std::ostream& s, const op::v9::ROIAlign::PoolingMode& type) {
return s << as_string(type);
}
std::ostream& ov::operator<<(std::ostream& s, const op::v9::ROIAlign::AlignedMode& type) {
return s << as_string(type);
}
namespace roi_alinop {
namespace {
template <element::Type_t ET>
@@ -148,7 +266,8 @@ bool evaluate(const HostTensorPtr& feature_maps,
const int sampling_ratio,
const float spatial_scale,
const op::v3::ROIAlign::PoolingMode& pooling_mode,
const ov::Shape& batch_indices_shape) {
const ov::Shape& batch_indices_shape,
const op::v9::ROIAlign::AlignedMode& aligned_mode = op::v9::ROIAlign::AlignedMode::ASYMMETRIC) {
using T = typename element_type_traits<ET>::value_type;
runtime::reference::roi_align<T>(feature_maps->get_data_ptr<ET>(),
rois->get_data_ptr<ET>(),
@@ -162,7 +281,8 @@ bool evaluate(const HostTensorPtr& feature_maps,
pooled_width,
sampling_ratio,
spatial_scale,
pooling_mode);
pooling_mode,
aligned_mode);
return true;
}
@@ -172,7 +292,8 @@ bool evaluate_roi_align(const HostTensorVector& args,
const int pooled_width,
const int sampling_ratio,
const float spatial_scale,
const op::v3::ROIAlign::PoolingMode& pooling_mode) {
const op::v3::ROIAlign::PoolingMode& pooling_mode,
const op::v9::ROIAlign::AlignedMode& aligned_mode = op::v9::ROIAlign::AlignedMode::ASYMMETRIC) {
auto feature_maps = args[0];
auto rois = args[1];
auto batch_indices = args[2];
@@ -191,7 +312,8 @@ bool evaluate_roi_align(const HostTensorVector& args,
sampling_ratio,
spatial_scale,
pooling_mode,
batch_indices->get_shape());
batch_indices->get_shape(),
aligned_mode);
NGRAPH_TYPE_CASE(evaluate_roi_align,
f16,
feature_maps,
@@ -203,7 +325,8 @@ bool evaluate_roi_align(const HostTensorVector& args,
sampling_ratio,
spatial_scale,
pooling_mode,
batch_indices->get_shape());
batch_indices->get_shape(),
aligned_mode);
NGRAPH_TYPE_CASE(evaluate_roi_align,
f32,
feature_maps,
@@ -215,7 +338,8 @@ bool evaluate_roi_align(const HostTensorVector& args,
sampling_ratio,
spatial_scale,
pooling_mode,
batch_indices->get_shape());
batch_indices->get_shape(),
aligned_mode);
default:
rc = false;
break;
+54
View File
@@ -58,3 +58,57 @@ TEST(type_prop_layers, roi_align_incompatible_rois_second_dim) {
ASSERT_THROW(const auto unused = make_shared<op::v3::ROIAlign>(data, rois, batch_indices, 3, 4, 1, 1.0f, "avg"),
ngraph::NodeValidationFailure);
}
TEST(type_prop_layers, roi_align_9_basic_shape_inference) {
const auto data = make_shared<op::Parameter>(element::f32, Shape{2, 3, 5, 5});
const auto rois = make_shared<op::Parameter>(element::f32, Shape{7, 4});
const auto batch_indices = make_shared<op::Parameter>(element::i32, Shape{7});
const auto pooling_mode = EnumNames<op::v9::ROIAlign::PoolingMode>::as_enum("avg");
const auto aligned_mode = EnumNames<op::v9::ROIAlign::AlignedMode>::as_enum("half_pixel_for_nn");
const auto op = make_shared<op::v9::ROIAlign>(data, rois, batch_indices, 2, 2, 1, 1.0f, pooling_mode, aligned_mode);
ASSERT_EQ(op->get_shape(), (Shape{7, 3, 2, 2}));
}
TEST(type_prop_layers, roi_align_9_dynamic_channels_dim) {
const auto data = make_shared<op::Parameter>(element::f32, PartialShape{10, Dimension(), 5, 5});
const auto rois = make_shared<op::Parameter>(element::f32, Shape{7, 4});
const auto batch_indices = make_shared<op::Parameter>(element::i32, Shape{7});
const auto pooling_mode = EnumNames<op::v9::ROIAlign::PoolingMode>::as_enum("avg");
const auto aligned_mode = EnumNames<op::v9::ROIAlign::AlignedMode>::as_enum("half_pixel_for_nn");
const auto op = make_shared<op::v9::ROIAlign>(data, rois, batch_indices, 3, 4, 1, 1.0f, pooling_mode, aligned_mode);
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{7, Dimension(), 3, 4}));
}
TEST(type_prop_layers, roi_align_9_num_rois_from_batch_indices) {
const auto data = make_shared<op::Parameter>(element::f32, PartialShape{10, 3, 5, 5});
const auto rois = make_shared<op::Parameter>(element::f32, PartialShape{Dimension{}, Dimension{}});
const auto batch_indices = make_shared<op::Parameter>(element::i32, Shape{9});
const auto pooling_mode = EnumNames<op::v9::ROIAlign::PoolingMode>::as_enum("avg");
const auto aligned_mode = EnumNames<op::v9::ROIAlign::AlignedMode>::as_enum("asymmetric");
const auto op = make_shared<op::v9::ROIAlign>(data, rois, batch_indices, 3, 4, 1, 1.0f, pooling_mode, aligned_mode);
ASSERT_EQ(op->get_shape(), (Shape{9, 3, 3, 4}));
}
TEST(type_prop_layers, roi_align_9_incompatible_num_rois) {
const auto data = make_shared<op::Parameter>(element::f32, Shape{10, 3, 5, 5});
const auto rois = make_shared<op::Parameter>(element::f32, PartialShape{1, Dimension{}});
const auto batch_indices = make_shared<op::Parameter>(element::i32, Shape{2});
const auto pooling_mode = EnumNames<op::v9::ROIAlign::PoolingMode>::as_enum("avg");
const auto aligned_mode = EnumNames<op::v9::ROIAlign::AlignedMode>::as_enum("asymmetric");
// the first dimension of rois and batch_indices should be equal
ASSERT_THROW(
const auto unused =
make_shared<op::v9::ROIAlign>(data, rois, batch_indices, 3, 4, 1, 1.0f, pooling_mode, aligned_mode),
ngraph::NodeValidationFailure);
}
TEST(type_prop_layers, roi_align_9_default_aligned_mode) {
const auto data = make_shared<op::Parameter>(element::f32, Shape{10, 3, 5, 5});
const auto rois = make_shared<op::Parameter>(element::f32, PartialShape{1, Dimension{}});
const auto batch_indices = make_shared<op::Parameter>(element::i32, Shape{2});
const auto pooling_mode = EnumNames<op::v9::ROIAlign::PoolingMode>::as_enum("avg");
// the first dimension of rois and batch_indices should be equal
ASSERT_THROW(
const auto unused = make_shared<op::v9::ROIAlign>(data, rois, batch_indices, 3, 4, 1, 1.0f, pooling_mode),
ngraph::NodeValidationFailure);
}
+52 -11
View File
@@ -12,7 +12,7 @@
#include <cpu/x64/cpu_isa_traits.hpp>
#include "ie_parallel.hpp"
#include <selective_build.h>
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/opsets/opset9.hpp>
#include <cpu/x64/jit_generator.hpp>
#include "emitters/jit_load_store_emitters.hpp"
@@ -29,7 +29,8 @@ namespace ov {
namespace intel_cpu {
namespace node {
using ngPoolingMode = ngraph::op::v3::ROIAlign::PoolingMode;
using ngPoolingMode = ngraph::opset9::ROIAlign::PoolingMode;
using ngAlignedMode = ngraph::opset9::ROIAlign::AlignedMode;
#define GET_OFF(field) offsetof(jit_roi_align_call_args, field)
@@ -633,9 +634,9 @@ private:
bool ROIAlign::isSupportedOperation(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept {
try {
auto roiAlign = ngraph::as_type_ptr<const ngraph::opset3::ROIAlign>(op);
auto roiAlign = ngraph::as_type_ptr<const ngraph::opset9::ROIAlign>(op);
if (!roiAlign) {
errorMessage = "Only opset3 ROIAlign operation is supported";
errorMessage = "Only opset9 ROIAlign operation is supported";
return false;
}
@@ -644,6 +645,12 @@ bool ROIAlign::isSupportedOperation(const std::shared_ptr<const ngraph::Node>& o
errorMessage = "Doesn't support mode: " + ngraph::as_string(mode);
return false;
}
const ngAlignedMode alignedMode = roiAlign->get_aligned_mode();
if (alignedMode != ngAlignedMode::ASYMMETRIC && alignedMode != ngAlignedMode::HALF_PIXEL_FOR_NN && alignedMode != ngAlignedMode::HALF_PIXEL) {
errorMessage = "Doesn't support mode: " + ngraph::as_string(alignedMode);
return false;
}
} catch (...) {
return false;
}
@@ -656,7 +663,7 @@ ROIAlign::ROIAlign(const std::shared_ptr<ngraph::Node>& op, const dnnl::engine&
if (isSupportedOperation(op, errorMessage)) {
errorPrefix = "ROIPooling layer with name '" + getName() + "' ";
auto roiAlign = ngraph::as_type_ptr<const ngraph::opset3::ROIAlign>(op);
auto roiAlign = ngraph::as_type_ptr<const ngraph::opset9::ROIAlign>(op);
pooledH = roiAlign->get_pooled_h();
pooledW = roiAlign->get_pooled_w();
spatialScale = roiAlign->get_spatial_scale();
@@ -667,6 +674,14 @@ ROIAlign::ROIAlign(const std::shared_ptr<ngraph::Node>& op, const dnnl::engine&
} else if (m == ngPoolingMode::AVG) {
algorithm = Algorithm::ROIAlignAvg;
}
const ngAlignedMode mAligned = roiAlign->get_aligned_mode();
if (mAligned == ngAlignedMode::ASYMMETRIC) {
alignedMode = ROIAlignedMode::ra_asymmetric;
} else if (mAligned == ngAlignedMode::HALF_PIXEL_FOR_NN) {
alignedMode = ROIAlignedMode::ra_half_pixel_for_nn;
} else if (mAligned == ngAlignedMode::HALF_PIXEL) {
alignedMode = ROIAlignedMode::ra_half_pixel;
}
} else {
IE_THROW(NotImplemented) << errorMessage;
}
@@ -885,6 +900,28 @@ void ROIAlign::executeSpecified() {
else
srcIndexTbl.resize(realRois);
bool aligned = false;
float offset_src = 0;
float offset_dst = 0;
switch (alignedMode) {
case ROIAlignedMode::ra_half_pixel_for_nn: {
aligned = true;
offset_dst = -0.5;
break;
}
case ROIAlignedMode::ra_half_pixel: {
aligned = true;
offset_src = 0.5;
offset_dst = -0.5;
break;
}
case ROIAlignedMode::ra_asymmetric:
default: {
break;
}
}
parallel_for(realRois, [&](size_t n) {
int roiOff = n * 4;
const float* srcRoiPtr = &srcRoi[roiOff];
@@ -895,13 +932,17 @@ void ROIAlign::executeSpecified() {
IE_THROW() << "Demanded batch (id = " << roiBatchInd << ") doesn't exist";
}
float x1 = srcRoiPtr[0] * spatialScale;
float y1 = srcRoiPtr[1] * spatialScale;
float x2 = srcRoiPtr[2] * spatialScale;
float y2 = srcRoiPtr[3] * spatialScale;
float x1 = (srcRoiPtr[0] + offset_src) * spatialScale + offset_dst;
float y1 = (srcRoiPtr[1] + offset_src) * spatialScale + offset_dst;
float x2 = (srcRoiPtr[2] + offset_src) * spatialScale + offset_dst;
float y2 = (srcRoiPtr[3] + offset_src) * spatialScale + offset_dst;
float roiHeight = std::max(y2 - y1, 1.0f);
float roiWidth = std::max(x2 - x1, 1.0f);
float roiHeight = y2 - y1;
float roiWidth = x2 - x1;
if (!aligned) {
roiHeight = std::max(roiHeight, 1.0f);
roiWidth = std::max(roiWidth, 1.0f);
}
float binHeight = roiHeight / pooledH;
float binWidth = roiWidth / pooledW;
@@ -21,6 +21,12 @@ enum ROIAlignLayoutType {
nspc
};
enum ROIAlignedMode {
ra_asymmetric,
ra_half_pixel_for_nn,
ra_half_pixel
};
struct jit_roi_align_params {
Algorithm alg;
InferenceEngine::Precision data_prc;
@@ -79,6 +85,7 @@ private:
int pooledW = 7;
int samplingRatio = 2;
float spatialScale = 1.0f;
ROIAlignedMode alignedMode;
template <typename inputType, typename outputType>
void executeSpecified();
template<typename T>
+4
View File
@@ -83,6 +83,8 @@
#include <transformations/utils/utils.hpp>
#include <snippets/pass/collapse_subgraph.hpp>
#include "ngraph_transformations/snippets_mark_skipped.hpp"
#include <transformations/op_conversions/convert_roi_align_v9_to_v3.hpp>
#include <transformations/op_conversions/convert_roi_align_v3_to_v9.hpp>
#include <ngraph/opsets/opset1.hpp>
#include <ngraph/opsets/opset2.hpp>
@@ -409,11 +411,13 @@ static void TransformationUpToCPUSpecificOpSet(std::shared_ptr<ngraph::Function>
pass_config->disable<ngraph::pass::ConvertReduceSumToPooling>();
pass_config->disable<ngraph::pass::SliceToStridedSlice>();
pass_config->disable<ngraph::pass::ConvertDetectionOutput8ToDetectionOutput1>();
pass_config->disable<ngraph::pass::ConvertROIAlign9To3>();
pass_config->enable<ngraph::pass::NormalizeL2Decomposition>();
pass_config->enable<ngraph::pass::ConvertInterpolate1ToInterpolate4>();
pass_config->enable<ngraph::pass::ConvertGather1ToGather7>();
pass_config->enable<ngraph::pass::ConvertDetectionOutput1ToDetectionOutput8>();
pass_config->enable<ngraph::pass::ConvertROIAlign3To9>();
if (useLpt) {
CPU_LPT_SCOPE(LowPrecisionTransformations_Part3);
@@ -0,0 +1,77 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include <memory>
#include <ngraph/function.hpp>
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/opsets/opset9.hpp>
#include <ngraph/pass/manager.hpp>
#include <string>
#include <transformations/init_node_info.hpp>
#include <transformations/op_conversions/convert_roi_align_v3_to_v9.hpp>
#include "common_test_utils/ngraph_test_utils.hpp"
using namespace testing;
using namespace ngraph;
TEST_F(TransformationTestsF, ConvertROIAlign3To9) {
{
const int N = 1;
const int C = 3;
const int H = 5;
const int W = 5;
const int num_rois = 5;
const int pooled_height = 3;
const int pooled_width = 4;
const auto data_shape = Shape{N, C, H, W};
const auto rois_shape = Shape{num_rois, 4};
const auto data = std::make_shared<opset3::Parameter>(element::f32, data_shape);
const auto rois = std::make_shared<opset3::Parameter>(element::f32, rois_shape);
const auto batch_indices = std::make_shared<opset3::Parameter>(element::i32, Shape{num_rois});
auto roi_align = std::make_shared<opset3::ROIAlign>(data,
rois,
batch_indices,
pooled_height,
pooled_width,
2,
1.0f / 16.0f,
"avg");
function = std::make_shared<Function>(NodeVector{roi_align}, ParameterVector{data, rois, batch_indices});
manager.register_pass<pass::ConvertROIAlign3To9>();
}
{
const int N = 1;
const int C = 3;
const int H = 5;
const int W = 5;
const int num_rois = 5;
const int pooled_height = 3;
const int pooled_width = 4;
const auto data_shape = Shape{N, C, H, W};
const auto rois_shape = Shape{num_rois, 4};
const auto data = std::make_shared<opset9::Parameter>(element::f32, data_shape);
const auto rois = std::make_shared<opset9::Parameter>(element::f32, rois_shape);
const auto batch_indices = std::make_shared<opset9::Parameter>(element::i32, Shape{num_rois});
const auto pooling_mode = EnumNames<opset9::ROIAlign::PoolingMode>::as_enum("avg");
auto roi_align = std::make_shared<opset9::ROIAlign>(data,
rois,
batch_indices,
pooled_height,
pooled_width,
2,
1.0f / 16.0f,
pooling_mode);
function_ref = std::make_shared<Function>(NodeVector{roi_align}, ParameterVector{data, rois, batch_indices});
}
}
@@ -0,0 +1,110 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include <memory>
#include <ngraph/function.hpp>
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/opsets/opset9.hpp>
#include <ngraph/pass/manager.hpp>
#include <string>
#include <transformations/init_node_info.hpp>
#include <transformations/op_conversions/convert_roi_align_v9_to_v3.hpp>
#include "common_test_utils/ngraph_test_utils.hpp"
using namespace testing;
using namespace ngraph;
TEST_F(TransformationTestsF, ConvertROIAlign9To3) {
{
const int N = 1;
const int C = 3;
const int H = 5;
const int W = 5;
const int num_rois = 5;
const int pooled_height = 3;
const int pooled_width = 4;
const auto data_shape = Shape{N, C, H, W};
const auto rois_shape = Shape{num_rois, 4};
const auto data = std::make_shared<opset9::Parameter>(element::f32, data_shape);
const auto rois = std::make_shared<opset9::Parameter>(element::f32, rois_shape);
const auto batch_indices = std::make_shared<opset9::Parameter>(element::i32, Shape{num_rois});
const auto pooling_mode = EnumNames<opset9::ROIAlign::PoolingMode>::as_enum("avg");
auto roi_align = std::make_shared<opset9::ROIAlign>(data,
rois,
batch_indices,
pooled_height,
pooled_width,
2,
1.0f / 16.0f,
pooling_mode);
function = std::make_shared<Function>(NodeVector{roi_align}, ParameterVector{data, rois, batch_indices});
manager.register_pass<pass::ConvertROIAlign9To3>();
}
{
const int N = 1;
const int C = 3;
const int H = 5;
const int W = 5;
const int num_rois = 5;
const int pooled_height = 3;
const int pooled_width = 4;
const auto data_shape = Shape{N, C, H, W};
const auto rois_shape = Shape{num_rois, 4};
const auto data = std::make_shared<opset9::Parameter>(element::f32, data_shape);
const auto rois = std::make_shared<opset9::Parameter>(element::f32, rois_shape);
const auto batch_indices = std::make_shared<opset9::Parameter>(element::i32, Shape{num_rois});
auto roi_align = std::make_shared<opset3::ROIAlign>(data,
rois,
batch_indices,
pooled_height,
pooled_width,
2,
1.0f / 16.0f,
"avg");
function_ref = std::make_shared<Function>(NodeVector{roi_align}, ParameterVector{data, rois, batch_indices});
}
}
TEST_F(TransformationTestsF, ConvertROIAlign9To3_aligned_mode) {
{
const int N = 1;
const int C = 3;
const int H = 5;
const int W = 5;
const int num_rois = 5;
const int pooled_height = 3;
const int pooled_width = 4;
const auto data_shape = Shape{N, C, H, W};
const auto rois_shape = Shape{num_rois, 4};
const auto data = std::make_shared<opset9::Parameter>(element::f32, data_shape);
const auto rois = std::make_shared<opset9::Parameter>(element::f32, rois_shape);
const auto batch_indices = std::make_shared<opset9::Parameter>(element::i32, Shape{num_rois});
const auto pooling_mode = EnumNames<opset9::ROIAlign::PoolingMode>::as_enum("avg");
const auto aligned_mode = EnumNames<opset9::ROIAlign::AlignedMode>::as_enum("half_pixel_for_nn");
auto roi_align = std::make_shared<opset9::ROIAlign>(data,
rois,
batch_indices,
pooled_height,
pooled_width,
2,
1.0f / 16.0f,
pooling_mode,
aligned_mode);
function = std::make_shared<Function>(NodeVector{roi_align}, ParameterVector{data, rois, batch_indices});
manager.register_pass<pass::ConvertROIAlign9To3>();
}
}
@@ -22,6 +22,7 @@ using ROIAlignSpecificParams = std::tuple<
float, // scale for given region considering actual input size
int, // pooling ratio
std::string, // pooling mode
std::string, // aligned mode
ROIAlignShapes
>;
@@ -52,8 +53,9 @@ public:
float spatialScale;
int samplingRatio;
std::string mode;
std::string alignedMode;
ROIAlignShapes inputShapes;
std::tie(pooledH, pooledW, spatialScale, samplingRatio, mode, inputShapes) = roiPar;
std::tie(pooledH, pooledW, spatialScale, samplingRatio, mode, alignedMode, inputShapes) = roiPar;
std::ostringstream result;
result << netPrecision << "_IS=";
@@ -74,6 +76,7 @@ public:
result << "spatialScale=" << spatialScale << "_";
result << "samplingRatio=" << samplingRatio << "_";
result << mode << "_";
result << alignedMode << "_";
result << CPUTestsBase::getTestCaseName(cpuParams);
return result.str();
@@ -138,16 +141,19 @@ protected:
float spatialScale;
int samplingRatio;
std::string mode;
std::string alignedMode;
ROIAlignShapes inputShapes;
std::tie(pooledH, pooledW, spatialScale, samplingRatio, mode, inputShapes) = roiAlignParams;
std::tie(pooledH, pooledW, spatialScale, samplingRatio, mode, alignedMode, inputShapes) = roiAlignParams;
init_input_shapes(inputShapes);
auto float_params = ngraph::builder::makeDynamicParams(inputPrecision, { inputDynamicShapes[0], inputDynamicShapes[1] });
auto int_params = ngraph::builder::makeDynamicParams(ngraph::element::i32, { inputDynamicShapes[2] });
auto pooling_mode = ngraph::EnumNames<ngraph::opset9::ROIAlign::PoolingMode>::as_enum(mode);
auto aligned_mode = ngraph::EnumNames<ngraph::opset9::ROIAlign::AlignedMode>::as_enum(alignedMode);
auto roialign = std::make_shared<ngraph::opset3::ROIAlign>(float_params[0], float_params[1], int_params[0], pooledH, pooledW,
samplingRatio, spatialScale, mode);
auto roialign = std::make_shared<ngraph::opset9::ROIAlign>(float_params[0], float_params[1], int_params[0], pooledH, pooledW,
samplingRatio, spatialScale, pooling_mode, aligned_mode);
selectedType = makeSelectedTypeStr(selectedType, inputPrecision);
if (inputPrecision == ElementType::bf16) {
@@ -206,6 +212,12 @@ const std::vector<std::string> modeVector = {
"max"
};
const std::vector<std::string> alignedModeVector = {
"asymmetric",
"half_pixel_for_nn",
"half_pixel"
};
const std::vector<ROIAlignShapes> inputShapeVector = {
ROIAlignShapes{{{}, {{ 2, 22, 20, 20 }}}, {{}, {{2, 4}}}, {{}, {{2}}}},
ROIAlignShapes{{{}, {{ 2, 18, 20, 20 }}}, {{}, {{2, 4}}}, {{}, {{2}}}},
@@ -239,6 +251,7 @@ const auto roiAlignParams = ::testing::Combine(
::testing::ValuesIn(spatialScaleVector), // scale for given region considering actual input size
::testing::ValuesIn(poolingRatioVector), // pooling ratio for bin
::testing::ValuesIn(modeVector), // pooling mode
::testing::ValuesIn(alignedModeVector), // aligned mode
::testing::ValuesIn(inputShapeVector) // feature map shape
);
@@ -837,6 +837,18 @@ std::shared_ptr<ov::Model> generate(const std::shared_ptr<ov::op::v3::ROIAlign>
return std::make_shared<ov::Model>(results, params, "ROIAlignGraph");
}
std::shared_ptr<ov::Model> generate(const std::shared_ptr<ov::op::v9::ROIAlign>& node) {
const auto params = ngraph::builder::makeDynamicParams(ov::element::f16, {{2, 1, 16, 16}});
const auto coords = ngraph::builder::makeConstant<float16>(ov::element::f16, {2, 4}, {2, 2, 8, 8, 2, 2, 8, 8});
const auto roisIdx = ngraph::builder::makeConstant<int32_t>(ov::element::i32, {2}, {0, 1});
const auto pooling_mode = EnumNames<op::v9::ROIAlign::PoolingMode>::as_enum("avg");
const auto aligned_mode = EnumNames<op::v9::ROIAlign::AlignedMode>::as_enum("half_pixel_for_nn");
auto Node =
std::make_shared<ov::op::v9::ROIAlign>(params.at(0), coords, roisIdx, 2, 2, 2, 1, pooling_mode, aligned_mode);
ov::ResultVector results{std::make_shared<ov::op::v0::Result>(Node)};
return std::make_shared<ov::Model>(results, params, "ROIAlignGraph");
}
std::shared_ptr<ov::Model> generate(const std::shared_ptr<ov::op::v0::ROIPooling> &node) {
const auto params = ngraph::builder::makeDynamicParams(ov::element::f16, {{1, 3, 8, 8},
{1, 5}});
@@ -1769,6 +1781,7 @@ OpGenerator getOpGeneratorMap() {
#include "openvino/opsets/opset6_tbl.hpp"
#include "openvino/opsets/opset7_tbl.hpp"
#include "openvino/opsets/opset8_tbl.hpp"
#include "openvino/opsets/opset9_tbl.hpp"
#undef _OPENVINO_OP_REG
};
return opGeneratorMap;
@@ -76,6 +76,7 @@ CompareMap getCompareMap() {
#include "ngraph/opsets/opset6_tbl.hpp"
#include "ngraph/opsets/opset7_tbl.hpp"
#include "ngraph/opsets/opset8_tbl.hpp"
#include "ngraph/opsets/opset9_tbl.hpp"
#undef NGRAPH_OP
};
@@ -38,6 +38,7 @@ Summary::Summary() {
opsets.push_back(ngraph::get_opset6());
opsets.push_back(ngraph::get_opset7());
opsets.push_back(ngraph::get_opset8());
opsets.push_back(ngraph::get_opset9());
}
Summary &Summary::getInstance() {
@@ -15,6 +15,7 @@
#include <ngraph/opsets/opset6.hpp>
#include <ngraph/opsets/opset7.hpp>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/opsets/opset9.hpp>
#include "ngraph_functions/utils/data_utils.hpp"
#include "openvino/core/partial_shape.hpp"