Skip to content

Commit 8c52fa3

Browse files
authored
[VSINPU]Split/Pad and some element-wise OPs support (microsoft#22916)
### Description -Add split/pad/neg/not/ceil/round/min/max op support -Fix conv2d op default pads value issue -Add VSINPU EP to support python bindings ### Motivation and Context -New OPs support for VSINPU EP --------- Signed-off-by: Kee <xuke537@hotmail.com>
1 parent e8bf46a commit 8c52fa3

File tree

9 files changed

+417
-2
lines changed

9 files changed

+417
-2
lines changed

cmake/onnxruntime_python.cmake

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ target_link_libraries(onnxruntime_pybind11_state PRIVATE
170170
onnxruntime_session
171171
${onnxruntime_libs}
172172
${PROVIDERS_NNAPI}
173+
${PROVIDERS_VSINPU}
173174
${PROVIDERS_XNNPACK}
174175
${PROVIDERS_COREML}
175176
${PROVIDERS_RKNPU}
@@ -1018,4 +1019,13 @@ if (onnxruntime_USE_QNN)
10181019
endif()
10191020
endif()
10201021

1022+
if (onnxruntime_USE_VSINPU)
1023+
add_custom_command(
1024+
TARGET onnxruntime_pybind11_state POST_BUILD
1025+
COMMAND ${CMAKE_COMMAND} -E copy
1026+
$<TARGET_FILE:onnxruntime_providers_vsinpu>
1027+
$<TARGET_FILE_DIR:${build_output_target}>/onnxruntime/capi/
1028+
)
1029+
endif()
1030+
10211031
endif()

onnxruntime/core/providers/vsinpu/builders/impl/conv_op_builder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class ConvOpBuilder : public BaseOpBuilder {
112112
}
113113
}
114114
} else {
115-
auto pads = helper.Get("pads", std::vector<uint32_t>{0U, 0U});
115+
auto pads = helper.Get("pads", std::vector<uint32_t>{0U, 0U, 0U, 0U});
116116
if (group != 1 && group != weight_tensor->GetShape()[OChannel_idx]) {
117117
if (is_1d_conv) {
118118
op = graph_ep->GetGraph()

onnxruntime/core/providers/vsinpu/builders/impl/elementwise_op_builder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ ELEMENTWISE_OP_BUILDER(Floor, Floor);
6565
ELEMENTWISE_OP_BUILDER(Log, Log);
6666
ELEMENTWISE_OP_BUILDER(Sin, Sin);
6767
ELEMENTWISE_OP_BUILDER(HardSwish, HardSwish);
68+
ELEMENTWISE_OP_BUILDER(Neg, Neg);
69+
ELEMENTWISE_OP_BUILDER(Not, LogicalNot);
70+
ELEMENTWISE_OP_BUILDER(Ceil, Ceil);
71+
ELEMENTWISE_OP_BUILDER(Round, Round);
72+
ELEMENTWISE_OP_BUILDER(Min, Minimum);
73+
ELEMENTWISE_OP_BUILDER(Max, Maximum);
6874

6975
class PowOpBuilder : public BaseOpBuilder {
7076
bool IsOpSupported(const onnxruntime::GraphViewer& graph_viewer,
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/****************************************************************************
2+
*
3+
* Copyright (c) 2024 Vivante Corporation
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a
6+
* copy of this software and associated documentation files (the "Software"),
7+
* to deal in the Software without restriction, including without limitation
8+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9+
* and/or sell copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21+
* DEALINGS IN THE SOFTWARE.
22+
*
23+
*****************************************************************************/
24+
#pragma once
25+
#include <memory>
26+
#include <vector>
27+
#include <utility>
28+
#include <limits>
29+
#include <algorithm>
30+
#include "core/optimizer/initializer.h"
31+
#include "core/providers/vsinpu/builders/impl/base_op_builder.h"
32+
#include "core/providers/common.h"
33+
#include "core/providers/shared/utils/utils.h"
34+
35+
namespace onnxruntime {
36+
namespace vsi {
37+
namespace npu {
38+
39+
typedef tim::vx::ops::PadV2::pad_mode_type PadMode;
40+
41+
class PadOpBuilder : public BaseOpBuilder {
42+
public:
43+
int GetMinSupportedOpSet(const NodeUnit& /* node_unit */) const override { return 11; }
44+
bool IsOpSupported(const onnxruntime::GraphViewer& graph_viewer,
45+
const Node* node) const override {
46+
NodeAttrHelper helper(*node);
47+
const auto mode = helper.Get("mode", "constant");
48+
auto input_defs = node->InputDefs();
49+
size_t num_inputs = input_defs.size();
50+
auto input_shape = vsi::npu::util::GetTensorShape(*input_defs[0]);
51+
int32_t rank = input_shape.NumDimensions();
52+
const auto& initializers = graph_viewer.GetAllInitializedTensors();
53+
54+
if (mode == "wrap") {
55+
LOGS_DEFAULT(WARNING) << "`wrap` mode Pad is not currently supported for now.";
56+
return false;
57+
}
58+
if (mode == "constant") {
59+
if (num_inputs > 2 && input_defs[2]->Exists()) {
60+
// only support if `constant_value` input is a constant initializer
61+
if (!Contains(initializers, input_defs[2]->Name())) {
62+
LOGS_DEFAULT(WARNING) << "constant_value must be a constant initializer.";
63+
return false;
64+
}
65+
}
66+
}
67+
// only support if `pads` input is known and does not contain negative values
68+
{
69+
const auto* pads_initializer = graph_viewer.GetConstantInitializer(input_defs[1]->Name());
70+
if (!pads_initializer) {
71+
LOGS_DEFAULT(WARNING) << "pads must be a constant initializer";
72+
return false;
73+
}
74+
75+
Initializer unpacked_tensor(*pads_initializer);
76+
auto tensor_data = unpacked_tensor.DataAsSpan<int64_t>();
77+
for (size_t i = 0; i < unpacked_tensor.size(); i++) {
78+
if (tensor_data[i] < 0) {
79+
LOGS_DEFAULT(WARNING) << "Negative pad value is not supported: pads["
80+
<< i << "] = " << tensor_data[i];
81+
return false;
82+
}
83+
}
84+
}
85+
return true;
86+
}
87+
88+
bool HasSupportedInputOutputsImpl(const InitializedTensorSet& initializers,
89+
const NodeUnit& node_unit) const override {
90+
for (size_t i = 0; i < node_unit.Inputs().size(); ++i) {
91+
const auto& iodef = node_unit.Inputs()[i];
92+
if (0 == i) {
93+
if (!util::IsTypeSupported(&iodef.node_arg) ||
94+
(*iodef.node_arg.Type() == "tensor(int64)") ||
95+
(*iodef.node_arg.Type() == "tensor(bool)")) {
96+
LOGS_DEFAULT(WARNING) << "Unspport tensor data type:" << *iodef.node_arg.Type();
97+
return false;
98+
}
99+
} else if (1 == i) {
100+
if (!Contains(initializers, iodef.node_arg.Name())) {
101+
LOGS_DEFAULT(WARNING) << "pads must be a constant initializer.";
102+
return false;
103+
}
104+
} else if (2 == i) {
105+
if (iodef.node_arg.Exists() && !Contains(initializers, iodef.node_arg.Name())) {
106+
LOGS_DEFAULT(WARNING) << "constant_value must be a constant initializer.";
107+
return false;
108+
}
109+
} else if (i == 3) {
110+
if (!Contains(initializers, iodef.node_arg.Name())) {
111+
LOGS_DEFAULT(WARNING) << "axes must be a constant initializer..";
112+
return false;
113+
}
114+
}
115+
}
116+
return true;
117+
}
118+
119+
bool HandleBuildOp(vsi::npu::GraphEP* graph_ep,
120+
std::vector<std::shared_ptr<tim::vx::Tensor>>& inputs,
121+
std::vector<std::shared_ptr<tim::vx::Tensor>>& outputs,
122+
const NodeUnit& node_unit) override {
123+
LOGS_DEFAULT(VERBOSE) << "Creating Pad Op.";
124+
NodeAttrHelper helper(node_unit);
125+
const auto mode = helper.Get("mode", "constant");
126+
auto input_defs = node_unit.Inputs();
127+
PadMode pad_mode = PadMode::PAD_MODE_CONSTANT;
128+
float const_val = 0.0f;
129+
std::vector<int64_t> axes_tensor_data;
130+
int32_t input_rank = inputs[0]->GetShape().size();
131+
132+
if (mode == "constant") {
133+
pad_mode = PadMode::PAD_MODE_CONSTANT;
134+
} else if (mode == "reflect") {
135+
pad_mode = PadMode::PAD_MODE_REFLECT;
136+
} else if (mode == "edge") {
137+
pad_mode = PadMode::PAD_MODE_EDGE;
138+
} else {
139+
LOGS_DEFAULT(WARNING) << "`wrap` mode Pad is not currently supported for now.";
140+
return false;
141+
}
142+
143+
// `pads` input
144+
std::vector<int64_t> onnx_pads(inputs[1]->GetSpec().GetElementNum());
145+
inputs[1]->CopyDataFromTensor(onnx_pads.data());
146+
147+
// `constant_value` input
148+
if (inputs.size() > 2 && pad_mode == PadMode::PAD_MODE_CONSTANT) {
149+
if (input_defs[2].node_arg.Exists()) {
150+
inputs[2]->CopyDataFromTensor(&const_val);
151+
}
152+
}
153+
// `axes` input
154+
if (inputs.size() > 3) {
155+
// optional input axes is provided, use axes initializer data
156+
std::vector<int64_t> axes_tensor(inputs[3]->GetSpec().GetElementNum());
157+
inputs[3]->CopyDataFromTensor(axes_tensor.data());
158+
std::transform(
159+
axes_tensor.begin(), axes_tensor.end(), std::back_inserter(axes_tensor_data),
160+
[input_rank](int64_t axis) { return HandleNegativeAxis(axis, input_rank); });
161+
} else {
162+
// if not provided, make a default axes as [0, 1, ..., input_rank - 1]
163+
std::vector<int64_t> default_axes(input_rank);
164+
std::iota(std::begin(default_axes), std::end(default_axes), 0);
165+
axes_tensor_data = std::move(default_axes);
166+
}
167+
168+
int64_t num_axes = axes_tensor_data.size();
169+
std::vector<uint32_t> front_size(input_rank, 0);
170+
std::vector<uint32_t> back_size(input_rank, 0);
171+
172+
int64_t axes_index = 0;
173+
for (int64_t axes : axes_tensor_data) {
174+
front_size[axes] = onnx_pads[axes_index];
175+
back_size[axes] = onnx_pads[axes_index + num_axes];
176+
axes_index++;
177+
}
178+
179+
std::reverse(front_size.begin(), front_size.end());
180+
std::reverse(back_size.begin(), back_size.end());
181+
182+
auto op = graph_ep->GetGraph()->CreateOperation<tim::vx::ops::PadV2>(
183+
front_size, back_size, const_val, pad_mode);
184+
op->BindInput(inputs[0]).BindOutputs(outputs);
185+
graph_ep->GetOps().push_back(std::move(op));
186+
return true;
187+
}
188+
};
189+
} // namespace npu
190+
} // namespace vsi
191+
} // namespace onnxruntime

0 commit comments

Comments
 (0)