Skip to content

Commit 1c0ca0e

Browse files
authored
[ONNX] Extended ReduceMax by opsets 13,18,20 (#23475)
### Details: - Extended ReduceMax by opsets 13,18,20 - Updated a using opset for ONNX to 20 - Added tests for additional supported types - Enabled backend tests ### Tickets: - Closes #20555
1 parent d8c35e1 commit 1c0ca0e

11 files changed

+265
-21
lines changed

src/frontends/onnx/frontend/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ov_add_frontend(NAME onnx
1010
FILEDESCRIPTION "FrontEnd to load and convert ONNX file format"
1111
LINK_LIBRARIES openvino_onnx_common openvino::core::dev)
1212

13-
set(ONNX_OPSET_VERSION 18 CACHE INTERNAL "Supported version of ONNX operator set")
13+
set(ONNX_OPSET_VERSION 20 CACHE INTERNAL "Supported version of ONNX operator set")
1414
target_compile_definitions(${TARGET_NAME} PRIVATE ONNX_OPSET_VERSION=${ONNX_OPSET_VERSION})
1515

1616
ov_ncc_naming_style(FOR_TARGET ${TARGET_NAME}

src/frontends/onnx/frontend/src/op/reduce.cpp

+45-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "identity.hpp"
99
#include "openvino/frontend/exception.hpp"
1010
#include "openvino/op/constant.hpp"
11+
#include "openvino/op/convert.hpp"
1112
#include "openvino/op/exp.hpp"
1213
#include "openvino/op/log.hpp"
1314
#include "openvino/op/multiply.hpp"
@@ -94,6 +95,27 @@ const std::set<element::Type> supported_types_v1 =
9495
{element::u32, element::u64, element::i32, element::i64, element::f16, element::f32, element::f64};
9596
const std::set<element::Type> supported_types_v2 =
9697
{element::u32, element::u64, element::i32, element::i64, element::f16, element::f32, element::f64, element::bf16};
98+
const std::set<element::Type> supported_types_v3 = {element::u32,
99+
element::u64,
100+
element::i32,
101+
element::i64,
102+
element::f16,
103+
element::f32,
104+
element::f64,
105+
element::bf16,
106+
element::i8,
107+
element::u8};
108+
const std::set<element::Type> supported_types_v4 = {element::u32,
109+
element::u64,
110+
element::i32,
111+
element::i64,
112+
element::f16,
113+
element::f32,
114+
element::f64,
115+
element::bf16,
116+
element::i8,
117+
element::u8,
118+
element::boolean};
97119

98120
template <typename OpType>
99121
std::shared_ptr<ov::Node> make_ov_reduction_op(const Node& node,
@@ -177,11 +199,33 @@ namespace set_13 {
177199
ov::OutputVector reduce_sum(const ov::frontend::onnx::Node& node) {
178200
return {make_ov_reduction_op<v1::ReduceSum>(node, node.get_ov_inputs().at(0), supported_types_v2, false)};
179201
}
202+
ov::OutputVector reduce_max(const ov::frontend::onnx::Node& node) {
203+
return {make_ov_reduction_op<v1::ReduceMax>(node, node.get_ov_inputs().at(0), supported_types_v3)};
204+
}
180205
} // namespace set_13
181206

182207
namespace set_18 {
183-
// Placeholder
208+
ov::OutputVector reduce_max(const ov::frontend::onnx::Node& node) {
209+
return {make_ov_reduction_op<v1::ReduceMax>(node, node.get_ov_inputs().at(0), supported_types_v3, false)};
210+
}
184211
} // namespace set_18
212+
213+
namespace set_20 {
214+
ov::OutputVector reduce_max(const ov::frontend::onnx::Node& node) {
215+
auto data = node.get_ov_inputs().at(0);
216+
if (data.get_element_type() != element::boolean) {
217+
return {make_ov_reduction_op<v1::ReduceMax>(node, data, supported_types_v3, false)};
218+
} else {
219+
// Handling boolean as a uint8
220+
return {std::make_shared<v0::Convert>(
221+
make_ov_reduction_op<v1::ReduceMax>(node,
222+
std::make_shared<ov::op::v0::Convert>(data, element::u8),
223+
supported_types_v4,
224+
false),
225+
element::boolean)};
226+
}
227+
}
228+
} // namespace set_20
185229
} // namespace op
186230
} // namespace onnx
187231
} // namespace frontend

src/frontends/onnx/frontend/src/op/reduce.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ ov::OutputVector reduce_l2(const ov::frontend::onnx::Node& node);
2929
namespace set_1 {
3030
ov::OutputVector reduce_max(const ov::frontend::onnx::Node& node);
3131
} // namespace set_1
32+
namespace set_13 {
33+
ov::OutputVector reduce_max(const ov::frontend::onnx::Node& node);
34+
} // namespace set_13
35+
namespace set_18 {
36+
ov::OutputVector reduce_max(const ov::frontend::onnx::Node& node);
37+
} // namespace set_18
38+
namespace set_20 {
39+
ov::OutputVector reduce_max(const ov::frontend::onnx::Node& node);
40+
} // namespace set_20
3241

3342
namespace set_1 {
3443
ov::OutputVector reduce_mean(const ov::frontend::onnx::Node& node);

src/frontends/onnx/frontend/src/ops_bridge.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,9 @@ OperatorsBridge::OperatorsBridge() {
484484
REGISTER_OPERATOR("ReduceL1", 1, reduce_l1);
485485
REGISTER_OPERATOR("ReduceL2", 1, reduce_l2);
486486
REGISTER_OPERATOR("ReduceMax", 1, reduce_max);
487+
REGISTER_OPERATOR("ReduceMax", 13, reduce_max);
488+
REGISTER_OPERATOR("ReduceMax", 18, reduce_max);
489+
REGISTER_OPERATOR("ReduceMax", 20, reduce_max);
487490
REGISTER_OPERATOR("ReduceMean", 1, reduce_mean);
488491
REGISTER_OPERATOR("ReduceMin", 1, reduce_min);
489492
REGISTER_OPERATOR("ReduceProd", 1, reduce_prod);

src/frontends/onnx/tests/__init__.py

-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True):
5959
xfail_issue_99954 = xfail_test(reason="Constant Pad - RuntimeError: Shape inference of Reference node with name y failed")
6060
xfail_issue_99955 = xfail_test(reason="GroupNorm is not supported")
6161
xfail_issue_99957 = xfail_test(reason="LayerNorm - RuntimeError: While validating node '<Node(Reshape): Mean>'")
62-
xfail_issue_99958 = xfail_test(reason="LogSoftmax - Results mismatch")
6362
xfail_issue_99960 = xfail_test(reason="MVN - Results mismatch")
6463
xfail_issue_99961 = xfail_test(reason="Optional has/get element operators are not supported)'")
6564
xfail_issue_99962 = pytest.mark.skip(reason="ReduceL1/L2 - Unrecognized attribute: axes for operator ReduceL1/L2")
@@ -71,7 +70,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True):
7170
xfail_issue_99970 = xfail_test(reason="Scatter and ScatterND - RuntimeError: Check '(reduction == none)' failed at "
7271
"src/frontends/onnx/frontend/src/op/scatter_elements.cpp OR at "
7372
"src/frontends/onnx/frontend/src/op/scatter_nd")
74-
xfail_issue_99972 = xfail_test(reason="Softmax - Results mismatch")
7573
xfail_issue_99973 = xfail_test(reason="Split - RuntimeError: While validating ONNX node "
7674
"'<Node(Split): output_1, output_2, output_3, output_4>'")
7775
xfail_issue_38710 = xfail_test(reason="RuntimeError: data has zero dimension which is not allowed")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
ir_version: 3
2+
producer_name: "OpenVINO ONNX Frontend"
3+
graph {
4+
node {
5+
input: "A"
6+
input: "axes"
7+
output: "B"
8+
op_type: "ReduceMax"
9+
}
10+
name: "compute_graph"
11+
initializer {
12+
data_type: 6
13+
dims: 1
14+
name: "axes"
15+
raw_data: "\002\000\000\000"
16+
}
17+
input {
18+
name: "A"
19+
type {
20+
tensor_type {
21+
elem_type: 2
22+
shape {
23+
dim {
24+
dim_value: 1
25+
}
26+
dim {
27+
dim_value: 1
28+
}
29+
dim {
30+
dim_value: 4
31+
}
32+
dim {
33+
dim_value: 4
34+
}
35+
}
36+
}
37+
}
38+
}
39+
input {
40+
name: "axes"
41+
type {
42+
tensor_type {
43+
elem_type: 6
44+
shape {
45+
dim {
46+
dim_value: 1
47+
}
48+
}
49+
}
50+
}
51+
}
52+
output {
53+
name: "B"
54+
type {
55+
tensor_type {
56+
elem_type: 2
57+
shape {
58+
dim {
59+
dim_value: 1
60+
}
61+
}
62+
}
63+
}
64+
}
65+
}
66+
opset_import {
67+
version: 18
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
ir_version: 3
2+
producer_name: "OpenVINO ONNX Frontend"
3+
graph {
4+
node {
5+
input: "A"
6+
output: "B"
7+
op_type: "ReduceMax"
8+
}
9+
name: "compute_graph"
10+
input {
11+
name: "A"
12+
type {
13+
tensor_type {
14+
elem_type: 9
15+
shape {
16+
dim {
17+
dim_value: 1
18+
}
19+
dim {
20+
dim_value: 1
21+
}
22+
dim {
23+
dim_value: 4
24+
}
25+
dim {
26+
dim_value: 4
27+
}
28+
}
29+
}
30+
}
31+
}
32+
output {
33+
name: "B"
34+
type {
35+
tensor_type {
36+
elem_type: 9
37+
shape {
38+
dim {
39+
dim_value: 1
40+
}
41+
}
42+
}
43+
}
44+
}
45+
}
46+
opset_import {
47+
version: 13
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
ir_version: 3
2+
producer_name: "OpenVINO ONNX Frontend"
3+
graph {
4+
node {
5+
input: "A"
6+
output: "B"
7+
op_type: "ReduceMax"
8+
}
9+
name: "compute_graph"
10+
input {
11+
name: "A"
12+
type {
13+
tensor_type {
14+
elem_type: 9
15+
shape {
16+
dim {
17+
dim_value: 1
18+
}
19+
dim {
20+
dim_value: 1
21+
}
22+
dim {
23+
dim_value: 4
24+
}
25+
dim {
26+
dim_value: 4
27+
}
28+
}
29+
}
30+
}
31+
}
32+
output {
33+
name: "B"
34+
type {
35+
tensor_type {
36+
elem_type: 9
37+
shape {
38+
dim {
39+
dim_value: 1
40+
}
41+
}
42+
}
43+
}
44+
}
45+
}
46+
opset_import {
47+
version: 20
48+
}

src/frontends/onnx/tests/onnx_import.in.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,28 @@ OPENVINO_TEST(${BACKEND_NAME}, onnx_model_reduce_max) {
974974
test_case.run();
975975
}
976976

977+
OPENVINO_TEST(${BACKEND_NAME}, onnx_model_reduce_max_18) {
978+
// TEMPLATE plugin has an issue with evaluation for u8 type
979+
if (std::string("${BACKEND_NAME}") == std::string("INTERPRETER")) {
980+
GTEST_SKIP();
981+
}
982+
983+
auto model = convert_model("reduce_max_18.onnx");
984+
985+
// input data shape (1, 1, 4, 4)
986+
std::vector<std::vector<uint8_t>> inputs{
987+
ov::test::NDArray<uint8_t, 4>({{{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}}})
988+
.get_vector()};
989+
990+
// output data shape (1,)
991+
auto expected_output = ov::test::NDArray<uint8_t, 1>({13, 14, 15, 16}).get_vector();
992+
993+
auto test_case = ov::test::TestCase(model, s_device);
994+
test_case.add_multiple_inputs(inputs);
995+
test_case.add_expected_output(expected_output);
996+
test_case.run();
997+
}
998+
977999
OPENVINO_TEST(${BACKEND_NAME}, onnx_model_reduce_max_invalid_axes) {
9781000
EXPECT_THROW(convert_model("reduce_max_invalid_axes.onnx"), ov::Exception);
9791001
}

src/frontends/onnx/tests/onnx_import_exceptions.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,24 @@ TEST(onnx_importer, exception_msg_onnx_reduce_wrong_type_v2) {
9292
FAIL() << "The ONNX model importer failed for unexpected reason";
9393
}
9494
}
95+
96+
TEST(onnx_importer, exception_msg_onnx_reduce_wrong_type_v3) {
97+
try {
98+
convert_model("reduce_wrong_type_v3.onnx");
99+
// Should have thrown, so fail if it didn't
100+
FAIL() << "ONNX Importer did not detected incorrect model!";
101+
} catch (const ::ov::Exception& e) {
102+
EXPECT_HAS_SUBSTRING(e.what(), std::string("Unsupported input type boolean"));
103+
}
104+
// On MacOS after we re-throw ov::Exception exception, we couldn't catch it as is,
105+
// thus below workaround.
106+
catch (const std::exception& e) {
107+
EXPECT_HAS_SUBSTRING(e.what(), std::string("Unsupported input type boolean"));
108+
} catch (...) {
109+
FAIL() << "The ONNX model importer failed for unexpected reason";
110+
}
111+
}
112+
113+
TEST(onnx_importer, no_exception_onnx_reduce_wrong_type_v4) {
114+
EXPECT_NO_THROW(convert_model("reduce_wrong_type_v4.onnx"));
115+
}

src/frontends/onnx/tests/tests_python/test_backend.py

-17
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,11 @@
5151
xfail_issue_99954,
5252
xfail_issue_99955,
5353
xfail_issue_99957,
54-
xfail_issue_99958,
5554
xfail_issue_99960,
5655
xfail_issue_99961,
5756
xfail_issue_99968,
5857
xfail_issue_99969,
5958
xfail_issue_99970,
60-
xfail_issue_99972,
6159
xfail_issue_99973,
6260
xfail_issue_101965,
6361
xfail_issue_113506,
@@ -453,10 +451,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None
453451
"OnnxBackendNodeModelTest.test_layer_normalization_4d_axis_negative_3_expanded_ver18_cpu",
454452
"OnnxBackendNodeModelTest.test_layer_normalization_default_axis_expanded_ver18_cpu",
455453
),
456-
(
457-
xfail_issue_99958,
458-
"OnnxBackendNodeModelTest.test_logsoftmax_large_number_expanded_ver18_cpu",
459-
),
460454
(
461455
xfail_issue_99960,
462456
"OnnxBackendNodeModelTest.test_mvn_expanded_ver18_cpu",
@@ -499,12 +493,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None
499493
"OnnxBackendNodeModelTest.test_reduce_log_sum_exp_negative_axes_keepdims_example_cpu",
500494
"OnnxBackendNodeModelTest.test_reduce_log_sum_exp_keepdims_random_cpu",
501495
"OnnxBackendNodeModelTest.test_reduce_log_sum_negative_axes_cpu",
502-
"OnnxBackendNodeModelTest.test_reduce_max_do_not_keepdims_example_cpu",
503-
"OnnxBackendNodeModelTest.test_reduce_max_do_not_keepdims_random_cpu",
504-
"OnnxBackendNodeModelTest.test_reduce_max_keepdims_example_cpu",
505-
"OnnxBackendNodeModelTest.test_reduce_max_keepdims_random_cpu",
506-
"OnnxBackendNodeModelTest.test_reduce_max_negative_axes_keepdims_example_cpu",
507-
"OnnxBackendNodeModelTest.test_reduce_max_negative_axes_keepdims_random_cpu",
508496
"OnnxBackendNodeModelTest.test_reduce_mean_do_not_keepdims_example_cpu",
509497
"OnnxBackendNodeModelTest.test_reduce_log_sum_exp_negative_axes_keepdims_random_cpu",
510498
"OnnxBackendNodeModelTest.test_reduce_mean_do_not_keepdims_random_cpu",
@@ -552,10 +540,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None
552540
"OnnxBackendNodeModelTest.test_scatternd_max_cpu",
553541
"OnnxBackendNodeModelTest.test_scatternd_min_cpu",
554542
),
555-
(
556-
xfail_issue_99972,
557-
"OnnxBackendNodeModelTest.test_softmax_large_number_expanded_ver18_cpu",
558-
),
559543
(
560544
xfail_issue_99973,
561545
"OnnxBackendNodeModelTest.test_split_1d_uneven_split_opset18_cpu",
@@ -732,7 +716,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None
732716
),
733717
(
734718
xfail_issue_125495,
735-
"OnnxBackendNodeModelTest.test_reduce_max_bool_inputs_cpu",
736719
"OnnxBackendNodeModelTest.test_reduce_min_bool_inputs_cpu",
737720
),
738721
(

0 commit comments

Comments
 (0)