Skip to content

Commit 4354147

Browse files
authored
[CPU][ARM] Pooling: support i32 indices output and NHWC indices layout (#28626)
### Details: - Allow both `u32` and `i32` as the 2nd `Pooling` output (indices) data type since this output may contain only positive values (according to OpenVINO operation specifications) - Support `NHWC` layout in the 2nd `Pooling` output (indices) ### Tickets: - CVS-159121
1 parent c365229 commit 4354147

File tree

4 files changed

+91
-8
lines changed

4 files changed

+91
-8
lines changed

src/plugins/intel_cpu/src/nodes/executors/acl/acl_pooling.cpp

+29-7
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,22 @@ bool AclPoolingExecutor::isSupported(const TensorInfo& srcTensorInfo,
5555
DEBUG_LOG("NCHW + CEIL gives an accuracy problem in ACL AvgPool. ACL executor will not be created.");
5656
return false;
5757
}
58-
DimensionRoundingType round =
59-
(poolingAttrs.rounding == op::RoundingType::CEIL) ? DimensionRoundingType::CEIL : DimensionRoundingType::FLOOR;
58+
DimensionRoundingType round;
59+
switch (poolingAttrs.rounding) {
60+
case op::RoundingType::FLOOR:
61+
round = DimensionRoundingType::FLOOR;
62+
break;
63+
case op::RoundingType::CEIL:
64+
round = DimensionRoundingType::CEIL;
65+
break;
66+
// CEIL_TORCH type is mapped to ACL CEIL type
67+
case op::RoundingType::CEIL_TORCH:
68+
round = DimensionRoundingType::CEIL;
69+
break;
70+
default:
71+
DEBUG_LOG("Unknown rounding type: ", poolingAttrs.rounding);
72+
return false;
73+
}
6074

6175
if (srcDimsSize == 5) {
6276
if (dstDescsSize > 1) {
@@ -89,7 +103,12 @@ bool AclPoolingExecutor::isSupported(const TensorInfo& srcTensorInfo,
89103
pool_info->pool_type = pool_type;
90104
pool_info->exclude_padding = exclude_padding;
91105
if (dstDescsSize > 1) {
92-
TensorInfo indTensorInfo = TensorInfo(shapeCast(*indDims), 1, arm_compute::DataType::U32, dataLayout);
106+
auto indShape = shapeCast(*indDims);
107+
if (dataLayout == arm_compute::DataLayout::NHWC) {
108+
changeLayoutToNH_C({&indShape});
109+
}
110+
// U32 is specified since this is the only data type supported by ACL
111+
TensorInfo indTensorInfo = TensorInfo(indShape, 1, arm_compute::DataType::U32, dataLayout);
93112
arm_compute::Status s =
94113
arm_compute::NEPoolingLayer::validate(&srcTensorInfo, &dstTensorInfo, *pool_info, &indTensorInfo);
95114
if (!s) {
@@ -178,10 +197,13 @@ bool AclPoolingExecutor::init(const PoolingAttrs& poolingAttrs,
178197
return false;
179198
}
180199
auto indDims = dstDescs[1]->getShape().getStaticDims();
181-
TensorInfo indTensorInfo = TensorInfo(shapeCast(indDims),
182-
1,
183-
precisionToAclDataType(dstDescs[1]->getPrecision()),
184-
getAclDataLayoutByMemoryDesc(dstDescs[1]));
200+
auto indShape = shapeCast(indDims);
201+
if (dstTensorInfo.data_layout() == arm_compute::DataLayout::NHWC) {
202+
changeLayoutToNH_C({&indShape});
203+
}
204+
// U32 is specified since this is the only data type supported by ACL
205+
TensorInfo indTensorInfo =
206+
TensorInfo(indShape, 1, arm_compute::DataType::U32, getAclDataLayoutByMemoryDesc(dstDescs[1]));
185207
indTensor.allocator()->init(indTensorInfo);
186208
exec_func = [this, pool_info]() -> std::unique_ptr<IFunction> {
187209
auto acl_op = std::make_unique<arm_compute::NEPoolingLayer>();

src/plugins/intel_cpu/src/nodes/executors/acl/acl_pooling.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class AclPoolingExecutorBuilder : public PoolingExecutorBuilder {
7979
return false;
8080
}
8181

82-
if (dstDescs.size() == 2u && dstDescs[1]->getPrecision() != ov::element::u32) {
82+
if (dstDescs.size() == 2u && !one_of(dstDescs[1]->getPrecision(), ov::element::u32, ov::element::i32)) {
8383
DEBUG_LOG("AclPoolingExecutor supports U32 as indices precisions only. ",
8484
"Passed indices precision: ",
8585
dstDescs[1]->getPrecision());

src/plugins/intel_cpu/src/nodes/pooling.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ bool Pooling::isSupportedOperation(const std::shared_ptr<const ov::Node>& op, st
158158
errorMessage = "Supported ops are MaxPool-1, MaxPool-8, MaxPool-14, AvgPool-1 and AvgPool-14";
159159
return false;
160160
}
161+
#if defined(OV_CPU_WITH_ACL)
162+
if (ov::as_type_ptr<const ov::op::v8::MaxPool>(op) ||
163+
ov::as_type_ptr<const ov::op::v14::MaxPool>(op)) {
164+
if (ov::as_type_ptr<const ov::op::util::MaxPoolBase>(op)->get_kernel() != ov::Shape(2,2)) {
165+
errorMessage = "Pooling indices returning source tensor coordinates is only supported for pool size 2x2";
166+
return false;
167+
}
168+
}
169+
#endif
161170
} catch (...) {
162171
return false;
163172
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (C) 2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include "custom/single_layer_tests/classes/pooling.hpp"
6+
#include "utils/cpu_test_utils.hpp"
7+
#include "utils/fusing_test_utils.hpp"
8+
#include "utils/filter_cpu_info.hpp"
9+
10+
using namespace CPUTestUtils;
11+
12+
namespace ov {
13+
namespace test {
14+
namespace Pooling {
15+
16+
const std::vector<maxPoolV8SpecificParams>& paramsMaxV144D_2x2kernel = {
17+
maxPoolV8SpecificParams{ {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0},
18+
ov::element::Type_t::i32, 0,
19+
ov::op::RoundingType::CEIL_TORCH, ov::op::PadType::SAME_UPPER },
20+
maxPoolV8SpecificParams{ {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0},
21+
ov::element::Type_t::i32, 0,
22+
ov::op::RoundingType::CEIL_TORCH, ov::op::PadType::SAME_LOWER }
23+
};
24+
25+
INSTANTIATE_TEST_SUITE_P(smoke_MaxPoolV14_CPU_4D_2x2Kernel, MaxPoolingV14LayerCPUTest,
26+
::testing::Combine(
27+
::testing::ValuesIn(paramsMaxV144D_2x2kernel),
28+
::testing::ValuesIn(inputShapes4D()),
29+
::testing::ValuesIn((inpOutPrecision())),
30+
::testing::ValuesIn(filterCPUInfo(vecCpuConfigsFusing_4D())),
31+
::testing::Values(CPUTestUtils::empty_plugin_config)),
32+
MaxPoolingV14LayerCPUTest::getTestCaseName);
33+
34+
const std::vector<maxPoolV8SpecificParams>& paramsMaxV144D_non2x2kernel = {
35+
maxPoolV8SpecificParams{ {11, 7}, {2, 2}, {1, 1}, {2, 2}, {2, 2},
36+
ov::element::Type_t::i32, 0,
37+
ov::op::RoundingType::CEIL_TORCH, ov::op::PadType::EXPLICIT},
38+
};
39+
40+
//The test checks that fallback to nGraph works for ACL non-supported cases
41+
INSTANTIATE_TEST_SUITE_P(smoke_MaxPoolV14_CPU_4D_non2x2Kernel_ref, MaxPoolingV14LayerCPUTest,
42+
::testing::Combine(
43+
::testing::ValuesIn(paramsMaxV144D_non2x2kernel),
44+
::testing::ValuesIn(inputShapes4D()),
45+
::testing::ValuesIn((inpOutPrecision())),
46+
::testing::Values(CPUSpecificParams{{}, {}, {"ref_any"}, "ref_any"}),
47+
::testing::Values(CPUTestUtils::empty_plugin_config)),
48+
MaxPoolingV14LayerCPUTest::getTestCaseName);
49+
50+
} // namespace Pooling
51+
} // namespace test
52+
} // namespace ov

0 commit comments

Comments
 (0)