mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-29 20:14:01 +00:00
[QNN EP] Improve Slice to support opset 9 (#15186)
### Description Improve Slice to support Onnx opset9 which has starts, ends & axes in node attributes. ### Motivation and Context To unblock some models.
This commit is contained in:
parent
d834ec895a
commit
5a2e43bdd5
1 changed files with 35 additions and 12 deletions
|
|
@ -13,9 +13,6 @@
|
|||
namespace onnxruntime {
|
||||
namespace qnn {
|
||||
|
||||
const int SLICE_MIN_INPUT = 3;
|
||||
const int SLICE_MAX_INPUT = 5;
|
||||
|
||||
class SliceOpBuilder : public BaseOpBuilder {
|
||||
public:
|
||||
SliceOpBuilder() : BaseOpBuilder("SliceOpBuilder") {}
|
||||
|
|
@ -38,6 +35,10 @@ class SliceOpBuilder : public BaseOpBuilder {
|
|||
|
||||
private:
|
||||
Status ExplictOpCheck(QnnModelWrapper& qnn_model_wrapper, const NodeUnit& node_unit) const;
|
||||
void GetDataFromAttribute(const NodeUnit& node_unit,
|
||||
TensorShapeVector& raw_starts,
|
||||
TensorShapeVector& raw_ends,
|
||||
TensorShapeVector& raw_axes) const;
|
||||
typedef struct {
|
||||
int32_t begin, end, stride;
|
||||
} Range;
|
||||
|
|
@ -46,19 +47,36 @@ class SliceOpBuilder : public BaseOpBuilder {
|
|||
|
||||
Status SliceOpBuilder::ExplictOpCheck(QnnModelWrapper& qnn_model_wrapper, const NodeUnit& node_unit) const {
|
||||
size_t input_count = node_unit.Inputs().size();
|
||||
ORT_RETURN_IF_NOT(input_count >= SLICE_MIN_INPUT && input_count <= SLICE_MAX_INPUT,
|
||||
"For ONNX Slice operation the expected number of inputs is between 3 and 5.");
|
||||
// Skip the first input. All other input need to be initializer
|
||||
for (size_t i = 1; i < node_unit.Inputs().size(); i++) {
|
||||
const auto& next_input = node_unit.Inputs()[i].node_arg.Name();
|
||||
if (!qnn_model_wrapper.IsInitializerInput(next_input)) {
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "QNN desn't support dynamic slice.");
|
||||
// Op set 9 only has 1 input with starts, ends, axes attribute
|
||||
// Op set > 9, starts, ends, axes are from node input
|
||||
if (input_count > 1) {
|
||||
// Skip the first input. All other input need to be initializer
|
||||
for (size_t i = 1; i < input_count; i++) {
|
||||
const auto& next_input = node_unit.Inputs()[i].node_arg.Name();
|
||||
if (!qnn_model_wrapper.IsInitializerInput(next_input)) {
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "QNN desn't support dynamic slice.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
void SliceOpBuilder::GetDataFromAttribute(const NodeUnit& node_unit,
|
||||
TensorShapeVector& raw_starts,
|
||||
TensorShapeVector& raw_ends,
|
||||
TensorShapeVector& raw_axes) const {
|
||||
NodeAttrHelper node_helper(node_unit);
|
||||
auto starts = node_helper.Get("starts", std::vector<int64_t>{0});
|
||||
raw_starts.assign(starts.begin(), starts.end());
|
||||
auto ends = node_helper.Get("ends", std::vector<int64_t>{0});
|
||||
raw_ends.assign(ends.begin(), ends.end());
|
||||
if (node_helper.HasAttr("axes")) {
|
||||
auto axes = node_helper.Get("axes", std::vector<int64_t>{0});
|
||||
raw_axes.assign(axes.begin(), axes.end());
|
||||
}
|
||||
}
|
||||
|
||||
// Note: For ONNX Slice operation the expected number of inputs is between 3 and 5
|
||||
Status SliceOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper,
|
||||
const NodeUnit& node_unit,
|
||||
|
|
@ -79,7 +97,13 @@ Status SliceOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper,
|
|||
std::vector<uint32_t> input0_shape;
|
||||
|
||||
auto inputs = node_unit.Inputs();
|
||||
for (size_t input_i = 0; input_i < inputs.size(); ++input_i) {
|
||||
auto input_count = inputs.size();
|
||||
// Opset 9, only 1 input, starts, ends, axes are in attribute
|
||||
if (1 == input_count) {
|
||||
GetDataFromAttribute(node_unit, raw_starts, raw_ends, raw_axes);
|
||||
}
|
||||
|
||||
for (size_t input_i = 0; input_i < input_count; ++input_i) {
|
||||
auto& input_name = inputs[input_i].node_arg.Name();
|
||||
if (input_name.empty()) {
|
||||
// Ignore unspecified/unused optional input
|
||||
|
|
@ -144,7 +168,6 @@ Status SliceOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
ORT_ENFORCE(input_i == 0, "QNN ReluMinMax operator expects only one input. other inputs, starts, ends, axes and steps are expected to be parameters, ie. initializer inputs in ONNX model");
|
||||
input0_shape = input_shape;
|
||||
|
||||
input_names.push_back(input_name);
|
||||
|
|
|
|||
Loading…
Reference in a new issue