Skip to content

Commit 267e6f9

Browse files
authored
[CPU][ARM] Enable SLT Interpolate tests on ARM (openvinotoolkit#26039)
### Details: - Interpolate SLT test file has been splitted into test class and test instances. - As were agreed with @EgorDuplensky there are dedicated test instances for x64 and arm since ACL supports very limited scope of Interpolate configuration. - While enabling tests on ARM it was found that ACL NEScale does not support scales mode with linear/linear_onnx and half_pixel/asymmetric, so additional limitation has been added. - To add the limitation mentioned above `shapeCalcMode` was moved from `Interpolate` node into `InterpolateAttrs` structure. - Enabled `fp16` in arm test instances - Enabled `NHWC` in arm test instances ### Tickets: - *ticket-id*
1 parent c0f7765 commit 267e6f9

File tree

9 files changed

+661
-373
lines changed

9 files changed

+661
-373
lines changed

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

+7
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ bool ov::intel_cpu::ACLInterpolateExecutorBuilder::isSupported(const ov::intel_c
187187
return false;
188188
}
189189

190+
if (interpolateAttrs.shapeCalcMode == InterpolateShapeCalcMode::scales &&
191+
one_of(interpolateAttrs.coordTransMode, InterpolateCoordTransMode::half_pixel, InterpolateCoordTransMode::asymmetric) &&
192+
one_of(interpolateAttrs.mode, InterpolateMode::linear, InterpolateMode::linear_onnx)) {
193+
DEBUG_LOG("ACL Interpolate does not support scales mode with linear/linear_onnx and half_pixel/asymmetric");
194+
return false;
195+
}
196+
190197
if (interpolateAttrs.mode == InterpolateMode::nearest &&
191198
!isSupportedConfiguration(interpolateAttrs, srcDescs, dstDescs)) {
192199
DEBUG_LOG("ACL Interpolate isSupportedConfiguration method fails for nearest mode");

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#pragma once
66

7-
#include "../interpolate.hpp"
7+
#include "nodes/executors/interpolate.hpp"
88
#include "arm_compute/runtime/NEON/functions/NEScale.h"
99
#include "arm_compute/runtime/Tensor.h"
1010

src/plugins/intel_cpu/src/nodes/executors/interpolate.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ enum class InterpolateShapeCalcMode {
4848
};
4949

5050
struct InterpolateAttrs {
51+
InterpolateShapeCalcMode shapeCalcMode = InterpolateShapeCalcMode::sizes;
5152
InterpolateMode mode = InterpolateMode::nearest;
5253
InterpolateCoordTransMode coordTransMode = InterpolateCoordTransMode::half_pixel;
5354
InterpolateNearestMode nearestMode = InterpolateNearestMode::round_prefer_floor;

src/plugins/intel_cpu/src/nodes/interpolate.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -1862,9 +1862,9 @@ Interpolate::Interpolate(const std::shared_ptr<ov::Node>& op, const GraphContext
18621862

18631863
const auto &interpShapeCalcMode = interpAttr.shape_calculation_mode;
18641864
if (interpShapeCalcMode == ngInterpShapeCalcMode::SCALES) {
1865-
shapeCalcMode = InterpolateShapeCalcMode::scales;
1865+
interpAttrs.shapeCalcMode = InterpolateShapeCalcMode::scales;
18661866
} else if (interpShapeCalcMode == ngInterpShapeCalcMode::SIZES) {
1867-
shapeCalcMode = InterpolateShapeCalcMode::sizes;
1867+
interpAttrs.shapeCalcMode = InterpolateShapeCalcMode::sizes;
18681868
} else {
18691869
OPENVINO_THROW(errorPrefix, " has unsupported shape calculation mode");
18701870
}
@@ -1925,14 +1925,14 @@ Interpolate::Interpolate(const std::shared_ptr<ov::Node>& op, const GraphContext
19251925

19261926
const auto &interpShapeCalcMode = interpAttr.shape_calculation_mode;
19271927
if (interpShapeCalcMode == ngInterpShapeCalcMode::SCALES) {
1928-
shapeCalcMode = InterpolateShapeCalcMode::scales;
1928+
interpAttrs.shapeCalcMode = InterpolateShapeCalcMode::scales;
19291929
const auto scalesNode = std::dynamic_pointer_cast<const ov::op::v0::Constant>(interp->get_input_node_shared_ptr(SIZE_OR_SCALE_ID_V11));
19301930
if (scalesNode) {
19311931
scales = scalesNode->cast_vector<float>();
19321932
isScaleConstant = true;
19331933
}
19341934
} else if (interpShapeCalcMode == ngInterpShapeCalcMode::SIZES) {
1935-
shapeCalcMode = InterpolateShapeCalcMode::sizes;
1935+
interpAttrs.shapeCalcMode = InterpolateShapeCalcMode::sizes;
19361936
} else {
19371937
OPENVINO_THROW(errorPrefix, " has unsupported shape calculation mode");
19381938
}
@@ -2074,7 +2074,7 @@ void Interpolate::initSupportedPrimitiveDescriptors() {
20742074
auto pushDesc = [&](LayoutType dataFormat, impl_desc_type implDetail, bool is_version11, bool useAclExecutor = false) {
20752075
config.inConfs[DATA_ID].setMemDesc(creatorsMap.at(dataFormat)->createSharedDesc(inputPrecision, getInputShapeAtPort(DATA_ID)));
20762076
if (is_version11) {
2077-
if (shapeCalcMode == InterpolateShapeCalcMode::sizes) {
2077+
if (interpAttrs.shapeCalcMode == InterpolateShapeCalcMode::sizes) {
20782078
config.inConfs[SIZE_OR_SCALE_ID_V11].setMemDesc(
20792079
creatorsMap.at(LayoutType::ncsp)->createSharedDesc(targetShapeType, getInputShapeAtPort(SIZE_OR_SCALE_ID_V11)));
20802080
} else {
@@ -2198,7 +2198,7 @@ bool Interpolate::needShapeInfer() const {
21982198
if (Node::inputShapesModified()) {
21992199
return true;
22002200
}
2201-
if (shapeCalcMode == InterpolateShapeCalcMode::scales) {
2201+
if (interpAttrs.shapeCalcMode == InterpolateShapeCalcMode::scales) {
22022202
if (lastScales.empty()) {
22032203
return true;
22042204
}
@@ -2225,9 +2225,9 @@ bool Interpolate::needShapeInfer() const {
22252225
void Interpolate::executeDynamicImpl(dnnl::stream strm) {
22262226
execute(strm);
22272227

2228-
const size_t port = shapeCalcMode == InterpolateShapeCalcMode::sizes ? TARGET_SHAPE_ID : get_scale_id();
2228+
const size_t port = interpAttrs.shapeCalcMode == InterpolateShapeCalcMode::sizes ? TARGET_SHAPE_ID : get_scale_id();
22292229
const auto &memory = getParentEdgeAt(port)->getMemory();
2230-
if (shapeCalcMode == InterpolateShapeCalcMode::scales) {
2230+
if (interpAttrs.shapeCalcMode == InterpolateShapeCalcMode::scales) {
22312231
const float *scales = memory.getDataAs<const float>();
22322232
lastScales.assign(scales, scales + memory.getDesc().getShape().getElementsCount());
22332233
} else {
@@ -2268,7 +2268,7 @@ void Interpolate::prepareParams() {
22682268
if (!srcMemPtr || !srcMemPtr->isAllocated())
22692269
OPENVINO_THROW(errorPrefix, " did not allocate input memory");
22702270

2271-
if (shapeCalcMode == InterpolateShapeCalcMode::sizes) {
2271+
if (interpAttrs.shapeCalcMode == InterpolateShapeCalcMode::sizes) {
22722272
auto tsMemPtr = getSrcMemoryAtPort(TARGET_SHAPE_ID);
22732273
if (!tsMemPtr || !tsMemPtr->isAllocated())
22742274
OPENVINO_THROW(errorPrefix, " did not allocate target shape memory");
@@ -2307,7 +2307,7 @@ void Interpolate::prepareParams() {
23072307
interpAttrs.layout = InterpolateLayoutType::by_channel;
23082308
}
23092309

2310-
if (shapeCalcMode == InterpolateShapeCalcMode::scales) {
2310+
if (interpAttrs.shapeCalcMode == InterpolateShapeCalcMode::scales) {
23112311
if (!isScaleConstant) {
23122312
const auto& scalesMem = getParentEdgeAt(get_scale_id())->getMemory();
23132313
const float* scalesData = scalesMem.getDataAs<const float>();
@@ -2460,7 +2460,7 @@ std::vector<float> Interpolate::getScales(const VectorDims &srcDimPad, const Vec
24602460
if (interpAttrs.mode == InterpolateMode::bilinear_pillow || interpAttrs.mode == InterpolateMode::bicubic_pillow) {
24612461
fullScales[axis] = static_cast<float>(dstDim[axis]) / static_cast<float>(srcDimPad[axis]);
24622462
} else {
2463-
fullScales[axis] = (shapeCalcMode == InterpolateShapeCalcMode::scales) ? scales[i] :
2463+
fullScales[axis] = (interpAttrs.shapeCalcMode == InterpolateShapeCalcMode::scales) ? scales[i] :
24642464
static_cast<float>(dstDim[axis]) / static_cast<float>(srcDimPad[axis]);
24652465
}
24662466
}

src/plugins/intel_cpu/src/nodes/interpolate.h

-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,6 @@ class Interpolate : public Node {
223223
static size_t getSpatialDimsNum(const Dim rank);
224224

225225
bool hasPad = false;
226-
InterpolateShapeCalcMode shapeCalcMode = InterpolateShapeCalcMode::sizes;
227226

228227
bool isAxesSpecified = false;
229228
std::vector<int> axes;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
// Copyright (C) 2024 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include "interpolate.hpp"
6+
#include "gtest/gtest.h"
7+
#include "utils/cpu_test_utils.hpp"
8+
#include "utils/general_utils.h"
9+
#include "openvino/pass/manager.hpp"
10+
#include "transformations/op_conversions/convert_interpolate11_downgrade.hpp"
11+
12+
using namespace CPUTestUtils;
13+
using namespace ov::intel_cpu;
14+
15+
namespace ov {
16+
namespace test {
17+
18+
std::string InterpolateLayerCPUTest::getTestCaseName(testing::TestParamInfo<InterpolateLayerCPUTestParamsSet> obj) {
19+
InterpolateSpecificParams specificParams;
20+
ShapeParams shapeParams;
21+
ElementType prec;
22+
CPUSpecificParams cpuParams;
23+
fusingSpecificParams fusingParams;
24+
ov::AnyMap additionalConfig;
25+
std::tie(specificParams, shapeParams, prec, cpuParams, fusingParams, additionalConfig) = obj.param;
26+
27+
ov::op::v11::Interpolate::InterpolateMode mode;
28+
ov::op::v11::Interpolate::CoordinateTransformMode transfMode;
29+
ov::op::v11::Interpolate::NearestMode nearMode;
30+
bool antiAlias;
31+
std::vector<size_t> padBegin;
32+
std::vector<size_t> padEnd;
33+
double cubeCoef;
34+
std::tie(mode, transfMode, nearMode, antiAlias, padBegin, padEnd, cubeCoef) = specificParams;
35+
36+
ov::op::v11::Interpolate::ShapeCalcMode shapeCalcMode;
37+
InputShape inputShapes;
38+
ov::test::utils::InputLayerType shapeInputType;
39+
std::vector<std::vector<float>> shapeDataForInput;
40+
std::vector<int64_t> axes;
41+
std::tie(shapeCalcMode, inputShapes, shapeInputType, shapeDataForInput, axes) = shapeParams;
42+
43+
using ov::test::utils::operator<<;
44+
std::ostringstream result;
45+
result << "ShapeCalcMode=" << shapeCalcMode << "_";
46+
result << "IS=";
47+
result << ov::test::utils::partialShape2str({inputShapes.first}) << "_";
48+
result << "TS=";
49+
for (const auto& shape : inputShapes.second) {
50+
result << ov::test::utils::vec2str(shape) << "_";
51+
}
52+
if (shapeCalcMode == ov::op::v11::Interpolate::ShapeCalcMode::SCALES) {
53+
result << "Scales=";
54+
} else {
55+
result << "Sizes=";
56+
}
57+
for (const auto &data : shapeDataForInput) {
58+
result << ov::test::utils::vec2str(data) << "_";
59+
}
60+
result << shapeInputType << "_";
61+
result << "InterpolateMode=" << mode << "_";
62+
result << "CoordinateTransformMode=" << transfMode << "_";
63+
result << "NearestMode=" << nearMode << "_";
64+
result << "CubeCoef=" << cubeCoef << "_";
65+
result << "Antialias=" << antiAlias << "_";
66+
result << "PB=" << ov::test::utils::vec2str(padBegin) << "_";
67+
result << "PE=" << ov::test::utils::vec2str(padEnd) << "_";
68+
result << "Axes=" << ov::test::utils::vec2str(axes) << "_";
69+
result << "PRC=" << prec << "_";
70+
71+
result << CPUTestsBase::getTestCaseName(cpuParams);
72+
result << CpuTestWithFusing::getTestCaseName(fusingParams);
73+
74+
if (!additionalConfig.empty()) {
75+
result << "_PluginConf";
76+
for (auto& item : additionalConfig) {
77+
result << "_" << item.first << "=" << item.second.as<std::string>();
78+
}
79+
}
80+
81+
return result.str();
82+
}
83+
84+
void InterpolateLayerCPUTest::generate_inputs(const std::vector<ov::Shape>& targetInputStaticShapes) {
85+
inputs.clear();
86+
const auto& funcInputs = function->inputs();
87+
for (size_t i = 0; i < funcInputs.size(); ++i) {
88+
const auto& funcInput = funcInputs[i];
89+
ov::Tensor tensor;
90+
91+
if (i == 1) {
92+
if (shapeCalcMode == ov::op::v4::Interpolate::ShapeCalcMode::SIZES) {
93+
tensor = ov::Tensor(funcInput.get_element_type(), targetInputStaticShapes[i], sizes[inferRequestNum].data());
94+
} else {
95+
tensor = ov::Tensor(funcInput.get_element_type(), targetInputStaticShapes[i], scales[inferRequestNum].data());
96+
}
97+
} else {
98+
ov::test::utils::InputGenerateData in_data;
99+
in_data.start_from = 0;
100+
in_data.range = 2560;
101+
in_data.resolution = 256;
102+
tensor = ov::test::utils::create_and_fill_tensor(funcInput.get_element_type(), targetInputStaticShapes[i], in_data);
103+
}
104+
105+
inputs.insert({funcInput.get_node_shared_ptr(), tensor});
106+
}
107+
inferRequestNum++;
108+
}
109+
110+
void InterpolateLayerCPUTest::configure_model() {
111+
ov::preprocess::PrePostProcessor p(function);
112+
{
113+
auto& params = function->get_parameters();
114+
for (size_t i = 0; i < params.size(); i++) {
115+
if (i > 0) {
116+
continue;
117+
}
118+
if (inType != ov::element::Type_t::undefined) {
119+
p.input(i).tensor().set_element_type(inType);
120+
}
121+
}
122+
}
123+
{
124+
auto results = function->get_results();
125+
for (size_t i = 0; i < results.size(); i++) {
126+
if (outType != ov::element::Type_t::undefined) {
127+
p.output(i).tensor().set_element_type(outType);
128+
}
129+
}
130+
}
131+
function = p.build();
132+
}
133+
134+
void InterpolateLayerCPUTest::SetUp() {
135+
targetDevice = ov::test::utils::DEVICE_CPU;
136+
137+
InterpolateSpecificParams specificParams;
138+
ShapeParams shapeParams;
139+
ElementType ngPrc;
140+
CPUSpecificParams cpuParams;
141+
fusingSpecificParams fusingParams;
142+
ov::AnyMap additionalConfig;
143+
std::tie(specificParams, shapeParams, ngPrc, cpuParams, fusingParams, additionalConfig) = this->GetParam();
144+
145+
std::tie(inFmts, outFmts, priority, selectedType) = cpuParams;
146+
std::tie(postOpMgrPtr, fusedOps) = fusingParams;
147+
configuration.insert(additionalConfig.begin(), additionalConfig.end());
148+
149+
ov::op::v11::Interpolate::InterpolateMode mode;
150+
ov::op::v11::Interpolate::CoordinateTransformMode transfMode;
151+
ov::op::v11::Interpolate::NearestMode nearMode;
152+
bool antiAlias;
153+
std::vector<size_t> padBegin;
154+
std::vector<size_t> padEnd;
155+
double cubeCoef;
156+
std::tie(mode, transfMode, nearMode, antiAlias, padBegin, padEnd, cubeCoef) = specificParams;
157+
158+
InputShape dataShape;
159+
ov::test::utils::InputLayerType shapeInputType;
160+
std::vector<std::vector<float>> shapeDataForInput;
161+
std::vector<int64_t> axes;
162+
std::tie(shapeCalcMode, dataShape, shapeInputType, shapeDataForInput, axes) = shapeParams;
163+
164+
if (shapeCalcMode == ov::op::v11::Interpolate::ShapeCalcMode::SCALES) {
165+
scales = shapeDataForInput;
166+
} else {
167+
sizes.resize(shapeDataForInput.size());
168+
for (size_t i = 0; i < shapeDataForInput.size(); i++) {
169+
for (size_t j = 0; j < shapeDataForInput[i].size(); j++) {
170+
sizes[i].push_back(shapeDataForInput[i][j]);
171+
}
172+
}
173+
}
174+
175+
std::vector<InputShape> inputShapes;
176+
inputShapes.push_back(dataShape);
177+
if (shapeInputType == ov::test::utils::InputLayerType::PARAMETER) {
178+
inputShapes.push_back(InputShape({static_cast<int64_t>(axes.size())}, std::vector<ov::Shape>(dataShape.second.size(), {axes.size()})));
179+
}
180+
181+
auto it = additionalConfig.find(ov::hint::inference_precision.name());
182+
if (it != additionalConfig.end() && it->second.as<ov::element::Type>() == ov::element::bf16) {
183+
inType = outType = ngPrc = ElementType::bf16;
184+
rel_threshold = 1e-2f;
185+
} else if (it != additionalConfig.end() && it->second.as<ov::element::Type>() == ov::element::f16) {
186+
inType = outType = ngPrc = ElementType::f16;
187+
rel_threshold = 1e-2f;
188+
} else {
189+
inType = outType = ngPrc;
190+
}
191+
192+
init_input_shapes(inputShapes);
193+
194+
ov::ParameterVector params{std::make_shared<ov::op::v0::Parameter>(ngPrc, inputDynamicShapes.front())};
195+
std::shared_ptr<ov::Node> sizesInput, scalesInput;
196+
if (shapeCalcMode == ov::op::v11::Interpolate::ShapeCalcMode::SCALES) {
197+
if (shapeInputType == ov::test::utils::InputLayerType::PARAMETER) {
198+
auto paramNode = std::make_shared<ov::op::v0::Parameter>(ElementType::f32, ov::Shape{scales.front().size()});
199+
params.push_back(paramNode);
200+
scalesInput = paramNode;
201+
} else {
202+
scalesInput = std::make_shared<ov::op::v0::Constant>(ElementType::f32, ov::Shape{scales.front().size()}, scales.front());
203+
}
204+
} else {
205+
if (shapeInputType == ov::test::utils::InputLayerType::PARAMETER) {
206+
auto paramNode = std::make_shared<ov::op::v0::Parameter>(ElementType::i32, ov::Shape{sizes.front().size()});
207+
params.push_back(paramNode);
208+
sizesInput = paramNode;
209+
} else {
210+
sizesInput = std::make_shared<ov::op::v0::Constant>(ElementType::i32, ov::Shape{sizes.front().size()}, sizes.front());
211+
}
212+
}
213+
auto axesInput = std::make_shared<ov::op::v0::Constant>(ElementType::i64, ov::Shape{axes.size()}, axes);
214+
215+
for (size_t i = 0; i < params.size(); i++) {
216+
params[i]->set_friendly_name(std::string("param_") + std::to_string(i));
217+
}
218+
219+
ov::op::v11::Interpolate::InterpolateAttrs interpAttr{mode, shapeCalcMode, padBegin, padEnd, transfMode, nearMode,
220+
antiAlias, cubeCoef};
221+
222+
std::shared_ptr<ov::op::v11::Interpolate> interp = nullptr;
223+
if (shapeCalcMode == ov::op::v11::Interpolate::ShapeCalcMode::SCALES) {
224+
interp = std::make_shared<ov::op::v11::Interpolate>(params[0], scalesInput, axesInput, interpAttr);
225+
} else {
226+
interp = std::make_shared<ov::op::v11::Interpolate>(params[0], sizesInput, axesInput, interpAttr);
227+
}
228+
229+
function = makeNgraphFunction(ngPrc, params, interp, "InterpolateCPU");
230+
231+
ov::pass::Manager m;
232+
m.register_pass<ov::pass::ConvertInterpolate11ToInterpolate4>();
233+
m.run_passes(function);
234+
if (selectedType.empty()) {
235+
selectedType = getPrimitiveType();
236+
}
237+
selectedType = makeSelectedTypeStr(selectedType, ngPrc);
238+
}
239+
240+
TEST_P(InterpolateLayerCPUTest, CompareWithRefs) {
241+
run();
242+
CheckPluginRelatedResults(compiledModel, "Interpolate");
243+
}
244+
245+
246+
namespace Interpolate {
247+
const std::vector<ov::op::v11::Interpolate::NearestMode> defNearestModes() {
248+
static const std::vector<ov::op::v11::Interpolate::NearestMode> defNearestModes {
249+
ov::op::v11::Interpolate::NearestMode::ROUND_PREFER_FLOOR
250+
};
251+
return defNearestModes;
252+
}
253+
254+
const std::vector<bool> antialias() {
255+
return { false };
256+
}
257+
258+
const std::vector<double> cubeCoefs() {
259+
return { -0.75f };
260+
}
261+
262+
} // namespace Interpolate
263+
} // namespace test
264+
} // namespace ov

0 commit comments

Comments
 (0)