Skip to content

Commit d871b14

Browse files
committed
"Add legacy executor implementation for Interpolate node"
1 parent 5b680ae commit d871b14

File tree

8 files changed

+209
-5
lines changed

8 files changed

+209
-5
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ enum class ExecutorType : uint8_t {
4242
Kleidiai,
4343
};
4444

45-
enum class OperationType : uint8_t { FullyConnected, MatMul, Convolution, Eltwise };
45+
enum class OperationType : uint8_t { FullyConnected, MatMul, Convolution, Eltwise, Interpolate };
4646

4747
std::string ExecutorTypeToString(ExecutorType type);
4848
ExecutorType ExecutorTypeFromString(const std::string& typeStr);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "nodes/executors/eltwise_config.hpp"
1212
#include "nodes/executors/executor_implementation.hpp"
1313
#include "nodes/executors/fullyconnected_config.hpp"
14+
#include "nodes/executors/interpolate.hpp"
1415
#include "nodes/executors/matmul_config.hpp"
1516

1617
namespace ov::intel_cpu {
@@ -41,4 +42,8 @@ const std::vector<ExecutorImplementation<EltwiseAttrs>>& getImplementations();
4142
template <>
4243
const std::vector<ExecutorImplementation<MatMulAttrs>>& getImplementations();
4344

45+
// Interpolate
46+
template <>
47+
const std::vector<ExecutorImplementation<InterpolateAttrs>>& getImplementations();
48+
4449
} // namespace ov::intel_cpu

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ static constexpr int MAX_INPUT_INTERPOLATE = 8;
2525

2626
namespace ov::intel_cpu {
2727

28+
namespace node {
29+
class Interpolate;
30+
} // namespace node
31+
2832
enum InterpolateLayoutType : uint8_t { planar, block, by_channel };
2933

3034
enum InterpolateMode : uint8_t { nearest, linear, linear_onnx, cubic, bilinear_pillow, bicubic_pillow };
@@ -63,6 +67,7 @@ struct InterpolateAttrs {
6367
// 2. axis alignment [1,2] to [2,3].
6468
// 3. config planar layout support and treated it as channel_first layout.
6569
bool NCHWAsNHWC = false;
70+
node::Interpolate* node = nullptr;
6671
};
6772

6873
inline VectorDims getPaddedInputShape(const VectorDims& srcDims,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include <memory>
6+
7+
#include "nodes/executors/implementation_utils.hpp"
8+
#include "nodes/executors/implementations.hpp"
9+
#include "nodes/executors/interpolate.hpp"
10+
#include "nodes/executors/interpolate_legacy.hpp"
11+
#include "nodes/interpolate.h"
12+
#include "openvino/core/except.hpp"
13+
14+
namespace ov::intel_cpu {
15+
16+
template <>
17+
const std::vector<ExecutorImplementation<InterpolateAttrs>>& getImplementations() {
18+
static const std::vector<ExecutorImplementation<InterpolateAttrs>> interpolateImplementations{
19+
ExecutorImplementation<InterpolateAttrs>{
20+
"interpolate_legacy",
21+
ExecutorType::Common,
22+
OperationType::Interpolate,
23+
SupportsAnyConfig<InterpolateAttrs>{},
24+
HasNoOptimalConfig<InterpolateAttrs>{},
25+
AcceptsAnyShape<InterpolateAttrs>,
26+
[](const InterpolateAttrs& attrs,
27+
[[maybe_unused]] const MemoryArgs& memory,
28+
const ExecutorContext::CPtr& context) -> ExecutorPtr {
29+
OPENVINO_ASSERT(attrs.node, "Interpolate legacy executor requires node");
30+
return std::make_shared<InterpolateLegacyExecutor>(attrs.node, context);
31+
}}};
32+
33+
return interpolateImplementations;
34+
}
35+
36+
} // namespace ov::intel_cpu
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include "interpolate_legacy.hpp"
6+
7+
#include "nodes/interpolate.h"
8+
9+
namespace ov::intel_cpu {
10+
11+
InterpolateLegacyExecutor::InterpolateLegacyExecutor(node::Interpolate* node,
12+
[[maybe_unused]] ExecutorContext::CPtr context)
13+
: m_node(node) {}
14+
15+
bool InterpolateLegacyExecutor::update([[maybe_unused]] const MemoryArgs& memory) {
16+
OPENVINO_ASSERT(m_node, "InterpolateLegacyExecutor received null node");
17+
if (!m_node->shapesDefined()) {
18+
return true;
19+
}
20+
m_implType = m_node->prepareForLegacyExecutor();
21+
return true;
22+
}
23+
24+
void InterpolateLegacyExecutor::execute([[maybe_unused]] const MemoryArgs& memory) {
25+
OPENVINO_ASSERT(m_node, "InterpolateLegacyExecutor received null node");
26+
m_node->executeLegacy();
27+
}
28+
29+
impl_desc_type InterpolateLegacyExecutor::implType() const {
30+
return m_implType;
31+
}
32+
33+
} // namespace ov::intel_cpu
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#pragma once
6+
7+
#include "nodes/executors/executor.hpp"
8+
9+
namespace ov::intel_cpu {
10+
11+
namespace node {
12+
class Interpolate;
13+
}
14+
15+
class InterpolateLegacyExecutor : public Executor {
16+
public:
17+
InterpolateLegacyExecutor(node::Interpolate* node, ExecutorContext::CPtr context);
18+
19+
bool update(const MemoryArgs& memory) override;
20+
void execute(const MemoryArgs& memory) override;
21+
impl_desc_type implType() const override;
22+
23+
private:
24+
node::Interpolate* m_node = nullptr;
25+
impl_desc_type m_implType = impl_desc_type::undef;
26+
};
27+
28+
} // namespace ov::intel_cpu

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

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,6 +1919,7 @@ Interpolate::Interpolate(const std::shared_ptr<ov::Node>& op, const GraphContext
19191919
if (isSupportedOperation(op, errorMessage)) {
19201920
const auto& inputDataShape = getInputShapeAtPort(DATA_ID);
19211921
dataRank = inputDataShape.getRank();
1922+
interpAttrs.node = this;
19221923
if (const auto interp = ov::as_type_ptr<const ov::op::v4::Interpolate>(op)) {
19231924
is_version11 = false;
19241925
const auto numInputs = inputShapes.size();
@@ -2207,14 +2208,24 @@ void Interpolate::initSupportedPrimitiveDescriptors() {
22072208

22082209
NodeConfig config;
22092210
config.outConfs.resize(1);
2211+
m_atoi.clear();
2212+
m_atoi[ARG_SRC] = DATA_ID;
2213+
22102214
if (is_version11) {
2215+
m_atoi[ARG_SRC_1] = SIZE_OR_SCALE_ID_V11;
2216+
if (isAxesSpecified) {
2217+
m_atoi[ARG_SRC_2] = AXES_ID_V11;
2218+
}
22112219
if (isAxesSpecified) {
22122220
config.inConfs.resize(3);
22132221
} else {
22142222
config.inConfs.resize(2);
22152223
}
22162224
} else {
2225+
m_atoi[ARG_SRC_1] = TARGET_SHAPE_ID;
2226+
m_atoi[ARG_SRC_2] = get_scale_id();
22172227
if (isAxesSpecified) {
2228+
m_atoi[ARG_SRC_3] = get_axis_id();
22182229
config.inConfs.resize(4);
22192230
} else {
22202231
config.inConfs.resize(3);
@@ -2441,8 +2452,16 @@ inline int Interpolate::get_axis_id() const {
24412452
return AXES_ID;
24422453
}
24432454

2444-
void Interpolate::prepareParams() {
2445-
CPU_NODE_ASSERT(shapesDefined(), "input/output dims aren't defined");
2455+
ExecutorFactoryPtr<InterpolateAttrs> Interpolate::createExecutorFactory(const MemoryDescArgs& descs,
2456+
const InterpolateAttrs& attrs) {
2457+
auto executionContext = std::make_shared<ExecutorContext>(context, getImplPriority());
2458+
return std::make_shared<ExecutorFactory<InterpolateAttrs>>(attrs, executionContext, descs);
2459+
}
2460+
2461+
impl_desc_type Interpolate::prepareForLegacyExecutor() {
2462+
if (!shapesDefined()) {
2463+
return impl_desc_type::undef;
2464+
}
24462465

24472466
auto dstMemPtr = getDstMemoryAtPort(0);
24482467
CPU_NODE_ASSERT(dstMemPtr && dstMemPtr->isDefined(), "has undefined destination memory");
@@ -2466,6 +2485,10 @@ void Interpolate::prepareParams() {
24662485
const NodeDesc* selected_pd = getSelectedPrimitiveDescriptor();
24672486
CPU_NODE_ASSERT(selected_pd, "did not set preferable primitive descriptor");
24682487

2488+
impl_desc_type implType = selected_pd->getImplementationType();
2489+
2490+
aclExecPtr.reset();
2491+
24692492
const auto& srcDimsOrign = srcMemPtr->getStaticDims();
24702493
const auto& dstDimsOrign = dstMemPtr->getStaticDims();
24712494

@@ -2546,9 +2569,11 @@ void Interpolate::prepareParams() {
25462569
srcMemoryDescs,
25472570
dstMemoryDescs,
25482571
{});
2549-
selectedPD->setImplementationType(aclExecPtr->getImplType());
2572+
OPENVINO_ASSERT(aclExecPtr, "ACL Interpolate executor creation failed");
2573+
implType = aclExecPtr->getImplType();
2574+
selectedPD->setImplementationType(implType);
25502575

2551-
return;
2576+
return implType;
25522577
}
25532578

25542579
InterpolateKey key = {interpAttrs, src5DDims, dst5DDims, scales5D, dnnl::primitive_attr()};
@@ -2585,6 +2610,22 @@ void Interpolate::prepareParams() {
25852610
execPtr = result.first;
25862611

25872612
lastOutputDims = dstDimsOrign;
2613+
2614+
return implType;
2615+
}
2616+
2617+
void Interpolate::prepareParams() {
2618+
if (!m_executor) {
2619+
return;
2620+
}
2621+
2622+
for (const auto& entry : m_atoi) {
2623+
m_memory[entry.first] = getSrcMemoryAtPort(entry.second);
2624+
}
2625+
m_memory[ARG_DST] = getDstMemoryAtPort(0);
2626+
2627+
m_executor->update(m_memory);
2628+
getSelectedPrimitiveDescriptor()->setImplementationType(m_executor->implType());
25882629
}
25892630

25902631
void Interpolate::createPrimitive() {
@@ -2605,6 +2646,35 @@ void Interpolate::createPrimitive() {
26052646
interpAttrs.inPrc = srcMemPtr->getDesc().getPrecision();
26062647
interpAttrs.outPrc = dstMemPtr->getDesc().getPrecision();
26072648

2649+
const auto* selected_pd = getSelectedPrimitiveDescriptor();
2650+
CPU_NODE_ASSERT(selected_pd, "did not set preferable primitive descriptor");
2651+
2652+
const auto& config = selected_pd->getConfig();
2653+
2654+
MemoryDescArgs descs;
2655+
for (const auto& entry : m_atoi) {
2656+
const int argId = entry.first;
2657+
const int inputIdx = entry.second;
2658+
descs[argId] = config.inConfs.at(inputIdx).getMemDesc();
2659+
}
2660+
descs[ARG_DST] = config.outConfs[0].getMemDesc();
2661+
2662+
m_memory.clear();
2663+
for (const auto& entry : m_atoi) {
2664+
const int argId = entry.first;
2665+
const int inputIdx = entry.second;
2666+
m_memory[argId] = getSrcMemoryAtPort(inputIdx);
2667+
}
2668+
m_memory[ARG_DST] = getDstMemoryAtPort(0);
2669+
2670+
auto attrs = interpAttrs;
2671+
attrs.node = this;
2672+
2673+
m_factory = createExecutorFactory(descs, attrs);
2674+
m_executor = m_factory->make(m_memory, false);
2675+
2676+
Node::createPrimitive();
2677+
26082678
if (shapesDefined() && isExecutable()) {
26092679
if (needPrepareParams()) {
26102680
prepareParams();
@@ -2685,6 +2755,14 @@ std::vector<float> Interpolate::getScales(const VectorDims& srcDimPad, const Vec
26852755
}
26862756

26872757
void Interpolate::execute([[maybe_unused]] const dnnl::stream& strm) {
2758+
if (!m_executor) {
2759+
return;
2760+
}
2761+
2762+
m_executor->execute(m_memory);
2763+
}
2764+
2765+
void Interpolate::executeLegacy() {
26882766
auto dstMemPtr = getDstMemoryAtPort(0);
26892767
auto srcMemPtr = getSrcMemoryAtPort(DATA_ID);
26902768

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,21 @@
1212
#include <oneapi/dnnl/dnnl.hpp>
1313
#include <oneapi/dnnl/dnnl_common.hpp>
1414
#include <string>
15+
#include <unordered_map>
1516

1617
#include "cpu_types.h"
1718
#include "executors/interpolate.hpp"
1819
#include "graph_context.h"
1920
#include "node.h"
21+
#include "nodes/executors/executor_factory.hpp"
22+
#include "nodes/executors/memory_arguments.hpp"
2023
#include "openvino/core/node.hpp"
2124
#include "openvino/core/type/element_type.hpp"
2225

26+
namespace ov::intel_cpu {
27+
class InterpolateLegacyExecutor;
28+
}
29+
2330
namespace ov::intel_cpu::node {
2431

2532
struct jit_interpolate_config_params {
@@ -103,6 +110,8 @@ class Interpolate : public Node {
103110
inline int get_axis_id() const;
104111

105112
private:
113+
friend class ov::intel_cpu::InterpolateLegacyExecutor;
114+
106115
bool is_version11 = true;
107116
InterpolateAttrs interpAttrs;
108117
size_t dataRank = 0;
@@ -351,6 +360,16 @@ class Interpolate : public Node {
351360

352361
bool canUseAclExecutor = false;
353362
std::shared_ptr<InterpolateExecutor> aclExecPtr = nullptr;
363+
364+
ExecutorFactoryPtr<InterpolateAttrs> createExecutorFactory(const MemoryDescArgs& descs,
365+
const InterpolateAttrs& attrs);
366+
impl_desc_type prepareForLegacyExecutor();
367+
void executeLegacy();
368+
369+
ExecutorFactoryPtr<InterpolateAttrs> m_factory;
370+
ExecutorPtr m_executor;
371+
MemoryArgs m_memory;
372+
std::unordered_map<int, int> m_atoi;
354373
};
355374

356375
} // namespace ov::intel_cpu::node

0 commit comments

Comments
 (0)