已合并
fix: reduce_min/reduce_max/reduce_prod/reduce_log_sum_exp axis empty onnx plugin #3424
RuiWang_创建于 6月18日
fix: reduce_min/reduce_max/reduce_prod/reduce_log_sum_exp axis empty onnx plugin #3424
已合并
RuiWang_创建于 6月18日
4 个文件变更+225-199
Mmath/reduce_log_sum_exp/framework/reduce_log_sum_exp_onnx_plugin.cpp+153-46
@@ -1,5 +1,5 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.2+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
3 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of3 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 * CANN Open Software License Agreement Version 2.0 (the "License").4 * CANN Open Software License Agreement Version 2.0 (the "License").
5 * Please refer to the License for details. You may not use this file except in compliance with the License.5 * Please refer to the License for details. You may not use this file except in compliance with the License.
@@ -11,28 +11,22 @@
11#include "onnx_common.h"11#include "onnx_common.h"
12#include "math/reduce_log_sum_exp/op_graph/reduce_log_sum_exp_proto.h"12#include "math/reduce_log_sum_exp/op_graph/reduce_log_sum_exp_proto.h"
13 13 
14-using namespace std;
15using namespace ge;14using namespace ge;
16using ge::Operator;15using ge::Operator;
17 16 
18namespace domi {17namespace domi {
18+using NodeProto = ge::onnx::NodeProto;
19+ 
19static Status ParseParamsReduceLogSumExp(const Message* op_src, ge::Operator& op_dest)20static Status ParseParamsReduceLogSumExp(const Message* op_src, ge::Operator& op_dest)
20{21{
21- const ge::onnx::NodeProto* node = dynamic_cast<const ge::onnx::NodeProto*>(op_src);22+ const NodeProto* node = dynamic_cast<const NodeProto*>(op_src);
22 if (node == nullptr) {23 if (node == nullptr) {
23 OP_LOGE(GetOpName(op_dest).c_str(), "Dynamic cast op_src to NodeProto failed.");24 OP_LOGE(GetOpName(op_dest).c_str(), "Dynamic cast op_src to NodeProto failed.");
24 return FAILED;25 return FAILED;
25 }26 }
26 27 
27- int op_input_size = node->input_size();
28- int op_output_size = node->output_size();
29- op_dest.DynamicInputRegister("x", op_input_size);
30- op_dest.DynamicOutputRegister("y", op_output_size);
31- op_dest.SetAttr("original_type", "ai.onnx::11::ReduceLogSumExp");
32- 
33 std::vector<int> v_axes = {};28 std::vector<int> v_axes = {};
34 bool keep_dims = true;29 bool keep_dims = true;
35- 
36 for (const auto& attr : node->attribute()) {30 for (const auto& attr : node->attribute()) {
37 if (attr.name() == "axes" && attr.type() == ge::onnx::AttributeProto::INTS) {31 if (attr.name() == "axes" && attr.type() == ge::onnx::AttributeProto::INTS) {
38 for (int i = 0; i < attr.ints_size(); i++) {32 for (int i = 0; i < attr.ints_size(); i++) {
@@ -40,26 +34,34 @@ static Status ParseParamsReduceLogSumExp(const Message* op_src, ge::Operator& op
40 }34 }
41 } else if (attr.name() == "keepdims" && attr.type() == ge::onnx::AttributeProto::INT) {35 } else if (attr.name() == "keepdims" && attr.type() == ge::onnx::AttributeProto::INT) {
42 keep_dims = (attr.i() == 1);36 keep_dims = (attr.i() == 1);
43- } else if (37+ }
44- attr.name() == "noop_with_empty_axes" && attr.type() == ge::onnx::AttributeProto::INT && attr.i() == 1) {38+ if (attr.name() == "noop_with_empty_axes" && attr.type() == ge::onnx::AttributeProto::INT && attr.i() == 1) {
45 OP_LOGW(GetOpName(op_dest).c_str(), "Only support noop_with_empty_axes=0, but 1 is obtained now");39 OP_LOGW(GetOpName(op_dest).c_str(), "Only support noop_with_empty_axes=0, but 1 is obtained now");
46 }40 }
47 }41 }
48 42 
49- int64_t len = v_axes.size();43+ int num = v_axes.size();
50 std::vector<int64_t> dims = {};44 std::vector<int64_t> dims = {};
51- if (len != 0) {45+ if (num != 0) {
52- dims.push_back(len);46+ dims.push_back(num);
47+ } else {
48+ dims.push_back(0);
53 }49 }
54- ge::Tensor tensor1 = Vec2Tensor(v_axes, dims, DT_INT32, ge::FORMAT_ND);50+ ge::Tensor tensor = Vec2Tensor(v_axes, dims, ge::DT_INT32, ge::FORMAT_NCHW);
55- op_dest.SetAttr("axes", tensor1);51+ 
56- op_dest.SetAttr("keep_dims", keep_dims);
57 op_dest.SetAttr("name", node->name());52 op_dest.SetAttr("name", node->name());
53+ op_dest.SetAttr("axes", tensor);
54+ op_dest.SetAttr("keep_dims", keep_dims);
55+ const int input = 2;
56+ const int output = 1;
57+ op_dest.DynamicInputRegister("x", input);
58+ op_dest.DynamicOutputRegister("y", output);
59+ op_dest.SetAttr("original_type", "ai.onnx::11::ReduceLogSumExp");
58 60 
59 return SUCCESS;61 return SUCCESS;
60}62}
61 63 
62-static Status ParseOpToGraphReduceLogSumExp(const Operator& op, Graph& graph)64+static Status ParseOpToGraphReduceLogSumExp(const ge::Operator& op, Graph& graph)
63{65{
64 std::string ori_name;66 std::string ori_name;
65 if (op.GetAttr("name", ori_name) != SUCCESS) {67 if (op.GetAttr("name", ori_name) != SUCCESS) {
@@ -67,45 +69,150 @@ static Status ParseOpToGraphReduceLogSumExp(const Operator& op, Graph& graph)
67 return FAILED;69 return FAILED;
68 }70 }
69 71 
70- bool flag = false;72+ auto data0 = op::Data((ori_name + "_data0").c_str()).set_attr_index(0);
71- ge::Tensor const_value;73+ 
72- if (op.GetAttr("axes", const_value) != SUCCESS) {74+ ge::Tensor axes;
75+ if (op.GetAttr("axes", axes) != SUCCESS) {
73 OP_LOGE(GetOpName(op).c_str(), "get axes from op failed");76 OP_LOGE(GetOpName(op).c_str(), "get axes from op failed");
74 return FAILED;77 return FAILED;
75 }78 }
76- if (op.GetAttr("keep_dims", flag) != SUCCESS) {79+ 
77- OP_LOGE(GetOpName(op).c_str(), "get value of keep_dims from op failed.");80+ auto data1 = op::Const((ori_name + "_data1").c_str()).set_attr_value(axes);
81+ auto reduce_log_sum_exp =
82+ op::ReduceLogSumExp((ori_name + "_ReduceLogSumExp").c_str()).set_input_x(data0).set_input_axes(data1);
83+ 
84+ bool keep_dims = false;
85+ if (op.GetAttr("keep_dims", keep_dims) != SUCCESS) {
86+ OP_LOGE(GetOpName(op).c_str(), "get keep_dims from op failed");
87+ return FAILED;
88+ }
89+ reduce_log_sum_exp.set_attr_keep_dims(keep_dims);
90+ 
91+ std::vector<ge::Operator> inputs{data0};
92+ std::vector<std::pair<ge::Operator, std::vector<size_t> > > outputs;
93+ outputs.emplace_back(reduce_log_sum_exp, std::vector<std::size_t>{0});
94+ graph.SetInputs(inputs).SetOutputs(outputs);
95+ 
96+ return SUCCESS;
97+}
98+ 
99+static Status ParseParamsReduceLogSumExp13(const Message* op_src, ge::Operator& op_dest)
100+{
101+ const NodeProto* node = dynamic_cast<const NodeProto*>(op_src);
102+ if (node == nullptr) {
103+ OP_LOGE("ReduceLogSumExp13", "Dynamic cast op_src to NodeProto failed.");
104+ return FAILED;
105+ }
106+ op_dest.SetAttr("original_type", "ai.onnx::13::ReduceLogSumExp");
107+ 
108+ int input_size = node->input_size();
109+ bool keep_dims = true;
110+ for (const auto& attr : node->attribute()) {
111+ if (attr.name() == "keepdims" && attr.type() == ge::onnx::AttributeProto::INT) {
112+ keep_dims = (attr.i() == 1);
113+ }
114+ }
115+ 
116+ // opset 13+: axes changed from attribute to input.
117+ // When input_size == 1, there is no axes input; store an empty axes tensor
118+ // so ParseOpToGraph can retrieve it via GetAttr and pass to Const.
119+ std::vector<int> axes = {};
120+ std::vector<int64_t> dims = {0};
121+ ge::Tensor axes_tensor = Vec2Tensor(axes, dims, ge::DT_INT32, ge::FORMAT_NCHW);
122+ op_dest.SetAttr("axes", axes_tensor);
123+ 
124+ op_dest.SetAttr("name", node->name());
125+ op_dest.SetAttr("input_size", input_size);
126+ op_dest.SetAttr("keep_dims", keep_dims);
127+ return SUCCESS;
128+}
129+ 
130+namespace {
131+struct ReduceLogSumExp13Prop {
132+ std::string ori_name;
133+ bool keep_dims = false;
134+ int input_num = 1;
135+};
136+ 
137+Status GetProperty(const Operator& op, ReduceLogSumExp13Prop& prop)
138+{
139+ if (op.GetAttr("name", prop.ori_name) != SUCCESS) {
140+ OP_LOGE(GetOpName(op).c_str(), "get name from op failed.");
78 return FAILED;141 return FAILED;
79 }142 }
80 143 
81- auto data0 = op::Data((ori_name + "_data0").c_str()).set_attr_index(0);144+ if (op.GetAttr("keep_dims", prop.keep_dims) != SUCCESS) {
82- auto const_op = op::Const((ori_name + "_const_data").c_str()).set_attr_value(const_value);145+ OP_LOGE(GetOpName(op).c_str(), "get keep_dims from op failed");
83- auto reduce_log_sum_exp = op::ReduceLogSumExp((ori_name + "_ReduceLogSumExp").c_str())146+ return FAILED;
84- .set_input_x(data0)147+ }
85- .set_input_axes(const_op)148+ 
86- .set_attr_keep_dims(flag);149+ if (op.GetAttr("input_size", prop.input_num) != SUCCESS) {
87- std::vector<Operator> inputs{data0, const_op};150+ OP_LOGE(GetOpName(op).c_str(), "get input_num from op failed");
88- std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;151+ return FAILED;
89- output_indexs.emplace_back(reduce_log_sum_exp, vector<std::size_t>{0});152+ }
90- graph.SetInputs(inputs).SetOutputs(output_indexs);153+ return SUCCESS;
154+}
155+ 
156+} // namespace
157+ 
158+static Status ParseOpToGraphReduceLogSumExp13(const Operator& op, Graph& graph)
159+{
160+ ReduceLogSumExp13Prop prop;
161+ if (GetProperty(op, prop) != SUCCESS) {
162+ return FAILED;
163+ }
164+ auto data0 = op::Data((prop.ori_name + "_data0").c_str()).set_attr_index(0);
165+ int num_input = 2;
166+ if (prop.input_num == 1) {
167+ ge::Tensor axes;
168+ if (op.GetAttr("axes", axes) != SUCCESS) {
169+ OP_LOGE(GetOpName(op).c_str(), "get axes from op failed");
170+ return FAILED;
171+ }
172+ auto data1 = op::Const((prop.ori_name + "_data1").c_str()).set_attr_value(axes);
173+ auto reduce_log_sum_exp = op::ReduceLogSumExp((prop.ori_name + "_ReduceLogSumExp").c_str())
174+ .set_input_x(data0)
175+ .set_input_axes(data1)
176+ .set_attr_keep_dims(prop.keep_dims);
177+ std::vector<Operator> inputs{data0};
178+ std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;
179+ output_indexs.emplace_back(reduce_log_sum_exp, vector<std::size_t>{0});
180+ graph.SetInputs(inputs).SetOutputs(output_indexs);
181+ } else if (prop.input_num == num_input) {
182+ auto data1 = op::Data((prop.ori_name + "_data1").c_str()).set_attr_index(1);
183+ auto reduce_log_sum_exp = op::ReduceLogSumExp((prop.ori_name + "_ReduceLogSumExp").c_str())
184+ .set_input_x(data0)
185+ .set_input_axes(data1)
186+ .set_attr_keep_dims(prop.keep_dims);
187+ std::vector<Operator> inputs{data0, data1};
188+ std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;
189+ output_indexs.emplace_back(reduce_log_sum_exp, vector<std::size_t>{0});
190+ graph.SetInputs(inputs).SetOutputs(output_indexs);
191+ } else {
192+ OP_LOGE(GetOpName(op).c_str(), "Input num or set attr is error");
193+ return FAILED;
194+ }
91 return SUCCESS;195 return SUCCESS;
92}196}
93 197 
94// register ReduceLogSumExp op info to GE198// register ReduceLogSumExp op info to GE
95REGISTER_CUSTOM_OP("PartitionedCall")199REGISTER_CUSTOM_OP("PartitionedCall")
96 .FrameworkType(ONNX)200 .FrameworkType(ONNX)
97- .OriginOpType({ge::AscendString("ai.onnx::8::ReduceLogSumExp"),201+ .OriginOpType(
98- ge::AscendString("ai.onnx::9::ReduceLogSumExp"),202+ {ge::AscendString("ai.onnx::8::ReduceLogSumExp"), ge::AscendString("ai.onnx::9::ReduceLogSumExp"),
99- ge::AscendString("ai.onnx::10::ReduceLogSumExp"),203+ ge::AscendString("ai.onnx::10::ReduceLogSumExp"), ge::AscendString("ai.onnx::11::ReduceLogSumExp"),
100- ge::AscendString("ai.onnx::11::ReduceLogSumExp"),204+ ge::AscendString("ai.onnx::12::ReduceLogSumExp")})
101- ge::AscendString("ai.onnx::12::ReduceLogSumExp"),
102- ge::AscendString("ai.onnx::13::ReduceLogSumExp"),
103- ge::AscendString("ai.onnx::14::ReduceLogSumExp"),
104- ge::AscendString("ai.onnx::15::ReduceLogSumExp"),
105- ge::AscendString("ai.onnx::16::ReduceLogSumExp"),
106- ge::AscendString("ai.onnx::17::ReduceLogSumExp"),
107- ge::AscendString("ai.onnx::18::ReduceLogSumExp")})
108 .ParseParamsFn(ParseParamsReduceLogSumExp)205 .ParseParamsFn(ParseParamsReduceLogSumExp)
109 .ParseOpToGraphFn(ParseOpToGraphReduceLogSumExp)206 .ParseOpToGraphFn(ParseOpToGraphReduceLogSumExp)
110 .ImplyType(ImplyType::TVM);207 .ImplyType(ImplyType::TVM);
111-} // namespace domi208+ 
209+REGISTER_CUSTOM_OP("ReduceLogSumExp")
210+ .FrameworkType(ONNX)
211+ .OriginOpType(
212+ {ge::AscendString("ai.onnx::13::ReduceLogSumExp"), ge::AscendString("ai.onnx::14::ReduceLogSumExp"),
213+ ge::AscendString("ai.onnx::15::ReduceLogSumExp"), ge::AscendString("ai.onnx::16::ReduceLogSumExp"),
214+ ge::AscendString("ai.onnx::17::ReduceLogSumExp"), ge::AscendString("ai.onnx::18::ReduceLogSumExp")})
215+ .ParseParamsFn(ParseParamsReduceLogSumExp13)
216+ .ParseOpToGraphFn(ParseOpToGraphReduceLogSumExp13)
217+ .ImplyType(ImplyType::TVM);
218+} // namespace domi
Mmath/reduce_max/framework/reduce_max_onnx_plugin.cpp+24-51
@@ -17,20 +17,6 @@ using ge::Operator;
17namespace domi {17namespace domi {
18using NodeProto = ge::onnx::NodeProto;18using NodeProto = ge::onnx::NodeProto;
19 19 
20-static Status GetInputTensorDimNum(const Operator& data_op, int64_t& dim_num)
21-{
22- ge::TensorDesc input_desc = data_op.GetInputDesc(0);
23- auto shape = input_desc.GetShape();
24- if (shape.GetDimNum() <= 0) {
25- OP_LOGE("GetInputTensorDimNum", "Get input shape is invalid.");
26- return FAILED;
27- }
28- 
29- dim_num = shape.GetDimNum();
30- OP_LOGI(GetOpName(data_op).c_str(), "GetInputTensorDimNum is: %ld", dim_num);
31- return SUCCESS;
32-}
33- 
34static Status ParseParamsReduceMax(const Message* op_src, ge::Operator& op_dest)20static Status ParseParamsReduceMax(const Message* op_src, ge::Operator& op_dest)
35{21{
36 const NodeProto* node = dynamic_cast<const NodeProto*>(op_src);22 const NodeProto* node = dynamic_cast<const NodeProto*>(op_src);
@@ -65,6 +51,7 @@ static Status ParseParamsReduceMax(const Message* op_src, ge::Operator& op_dest)
65 op_dest.SetAttr("name", node->name());51 op_dest.SetAttr("name", node->name());
66 op_dest.SetAttr("axes", tensor);52 op_dest.SetAttr("axes", tensor);
67 op_dest.SetAttr("keep_dims", keep_dims);53 op_dest.SetAttr("keep_dims", keep_dims);
54+ op_dest.SetAttr("noop_with_empty_axes", 0);
68 const int input = 2;55 const int input = 2;
69 const int output = 1;56 const int output = 1;
70 op_dest.DynamicInputRegister("x", input);57 op_dest.DynamicInputRegister("x", input);
@@ -90,24 +77,6 @@ static Status ParseOpToGraphReduceMax(const ge::Operator& op, Graph& graph)
90 return FAILED;77 return FAILED;
91 }78 }
92 79 
93- if (axes.GetSize() == 0) {
94- int64_t input_dim_num = 0;
95- if (GetInputTensorDimNum(op, input_dim_num) != SUCCESS) {
96- OP_LOGE(GetOpName(op).c_str(), "Failed to get input tensor dimensions");
97- return FAILED;
98- }
99- std::vector<int64_t> v_axes;
100- for (int64_t i = 0; i < input_dim_num; ++i) {
101- v_axes.push_back(i);
102- }
103- int num = v_axes.size();
104- std::vector<int64_t> dims = {};
105- if (num != 0) {
106- dims.push_back(num);
107- }
108- axes = Vec2Tensor(v_axes, dims, ge::DT_INT64);
109- }
110- 
111 auto data1 = op::Const((ori_name + "_data1").c_str()).set_attr_value(axes);80 auto data1 = op::Const((ori_name + "_data1").c_str()).set_attr_value(axes);
112 auto reducemax = op::ReduceMax((ori_name + "_ReduceMax").c_str()).set_input_x(data0).set_input_axes(data1);81 auto reducemax = op::ReduceMax((ori_name + "_ReduceMax").c_str()).set_input_x(data0).set_input_axes(data1);
113 82 
@@ -118,6 +87,13 @@ static Status ParseOpToGraphReduceMax(const ge::Operator& op, Graph& graph)
118 }87 }
119 reducemax.set_attr_keep_dims(keep_dims);88 reducemax.set_attr_keep_dims(keep_dims);
120 89 
90+ int noop_with_empty_axes = 0;
91+ if (op.GetAttr("noop_with_empty_axes", noop_with_empty_axes) != SUCCESS) {
92+ OP_LOGE(GetOpName(op).c_str(), "get noop_with_empty_axes from op failed");
93+ return FAILED;
94+ }
95+ reducemax.set_attr_noop_with_empty_axes(noop_with_empty_axes);
96+ 
121 std::vector<ge::Operator> inputs{data0};97 std::vector<ge::Operator> inputs{data0};
122 std::vector<std::pair<ge::Operator, std::vector<size_t> > > outputs;98 std::vector<std::pair<ge::Operator, std::vector<size_t> > > outputs;
123 outputs.emplace_back(reducemax, std::vector<std::size_t>{0});99 outputs.emplace_back(reducemax, std::vector<std::size_t>{0});
@@ -146,6 +122,14 @@ static Status ParseParamsReduceMax13(const Message* op_src, ge::Operator& op_des
146 }122 }
147 }123 }
148 124 
125+ // opset 13+: axes changed from attribute to input.
126+ // When input_size == 1, there is no axes input; store an empty axes tensor
127+ // so ParseOpToGraph can retrieve it via GetAttr and pass to Const.
128+ std::vector<int> axes = {};
129+ std::vector<int64_t> dims = {0};
130+ ge::Tensor axes_tensor = Vec2Tensor(axes, dims, ge::DT_INT32, ge::FORMAT_NCHW);
131+ op_dest.SetAttr("axes", axes_tensor);
132+ 
149 op_dest.SetAttr("name", node->name());133 op_dest.SetAttr("name", node->name());
150 op_dest.SetAttr("input_size", input_size);134 op_dest.SetAttr("input_size", input_size);
151 op_dest.SetAttr("keep_dims", keep_dims);135 op_dest.SetAttr("keep_dims", keep_dims);
@@ -195,31 +179,20 @@ static Status ParseOpToGraphReduceMax13(const Operator& op, Graph& graph)
195 }179 }
196 auto data0 = op::Data((prop.ori_name + "_data0").c_str()).set_attr_index(0);180 auto data0 = op::Data((prop.ori_name + "_data0").c_str()).set_attr_index(0);
197 int num_input = 2;181 int num_input = 2;
198- if (prop.input_num == 1 && prop.empty_axes == 0) {182+ if (prop.input_num == 1) {
199- int64_t input_dim_num = 0;183+ ge::Tensor axes;
200- if (GetInputTensorDimNum(op, input_dim_num) != SUCCESS) {184+ if (op.GetAttr("axes", axes) != SUCCESS) {
201- OP_LOGE(GetOpName(op).c_str(), "Failed to get input tensor dimensions");185+ OP_LOGE(GetOpName(op).c_str(), "get axes from op failed");
202 return FAILED;186 return FAILED;
203 }187 }
204- 188+ auto data1 = op::Const((prop.ori_name + "_data1").c_str()).set_attr_value(axes);
205- std::vector<int64_t> v_axes;
206- for (int64_t i = 0; i < input_dim_num; ++i) {
207- v_axes.push_back(i);
208- }
209- ge::TensorDesc tensorDesc;
210- std::vector<int64_t> dims = {input_dim_num};
211- ge::Shape shape(dims);
212- tensorDesc.SetShape(shape);
213- tensorDesc.SetDataType(DT_INT64);
214- ge::Tensor tensor(tensorDesc, reinterpret_cast<uint8_t*>(v_axes.data()), v_axes.size() * sizeof(int64_t));
215- auto axes = op::Const((prop.ori_name + "_axes").c_str()).set_attr_value(tensor);
216- std::vector<Operator> inputs{data0, axes};
217- std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;
218 auto reducemax = op::ReduceMax((prop.ori_name + "_ReduceMax").c_str())189 auto reducemax = op::ReduceMax((prop.ori_name + "_ReduceMax").c_str())
219 .set_input_x(data0)190 .set_input_x(data0)
220- .set_input_axes(axes)191+ .set_input_axes(data1)
221 .set_attr_keep_dims(prop.keep_dims)192 .set_attr_keep_dims(prop.keep_dims)
222 .set_attr_noop_with_empty_axes(prop.empty_axes);193 .set_attr_noop_with_empty_axes(prop.empty_axes);
194+ std::vector<Operator> inputs{data0};
195+ std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;
223 output_indexs.emplace_back(reducemax, vector<std::size_t>{0});196 output_indexs.emplace_back(reducemax, vector<std::size_t>{0});
224 graph.SetInputs(inputs).SetOutputs(output_indexs);197 graph.SetInputs(inputs).SetOutputs(output_indexs);
225 } else if (prop.input_num == num_input) {198 } else if (prop.input_num == num_input) {
Mmath/reduce_min/framework/reduce_min_onnx_plugin.cpp+24-51
@@ -17,20 +17,6 @@ using ge::Operator;
17namespace domi {17namespace domi {
18using NodeProto = ge::onnx::NodeProto;18using NodeProto = ge::onnx::NodeProto;
19 19 
20-static Status GetInputTensorDimNum(const Operator& data_op, int64_t& dim_num)
21-{
22- ge::TensorDesc input_desc = data_op.GetInputDesc(0);
23- auto shape = input_desc.GetShape();
24- if (shape.GetDimNum() <= 0) {
25- OP_LOGE("GetInputTensorDimNum", "Get input shape is invalid.");
26- return FAILED;
27- }
28- 
29- dim_num = shape.GetDimNum();
30- OP_LOGI(GetOpName(data_op).c_str(), "GetInputTensorDimNum is: %ld", dim_num);
31- return SUCCESS;
32-}
33- 
34static Status ParseParamsReduceMin(const Message* op_src, ge::Operator& op_dest)20static Status ParseParamsReduceMin(const Message* op_src, ge::Operator& op_dest)
35{21{
36 const NodeProto* node = dynamic_cast<const NodeProto*>(op_src);22 const NodeProto* node = dynamic_cast<const NodeProto*>(op_src);
@@ -65,6 +51,7 @@ static Status ParseParamsReduceMin(const Message* op_src, ge::Operator& op_dest)
65 op_dest.SetAttr("name", node->name());51 op_dest.SetAttr("name", node->name());
66 op_dest.SetAttr("axes", tensor);52 op_dest.SetAttr("axes", tensor);
67 op_dest.SetAttr("keep_dims", keep_dims);53 op_dest.SetAttr("keep_dims", keep_dims);
54+ op_dest.SetAttr("noop_with_empty_axes", 0);
68 const int input = 2;55 const int input = 2;
69 const int output = 1;56 const int output = 1;
70 op_dest.DynamicInputRegister("x", input);57 op_dest.DynamicInputRegister("x", input);
@@ -90,24 +77,6 @@ static Status ParseOpToGraphReduceMin(const ge::Operator& op, Graph& graph)
90 return FAILED;77 return FAILED;
91 }78 }
92 79 
93- if (axes.GetSize() == 0) {
94- int64_t input_dim_num = 0;
95- if (GetInputTensorDimNum(op, input_dim_num) != SUCCESS) {
96- OP_LOGE(GetOpName(op).c_str(), "Failed to get input tensor dimensions");
97- return FAILED;
98- }
99- std::vector<int64_t> v_axes;
100- for (int64_t i = 0; i < input_dim_num; ++i) {
101- v_axes.push_back(i);
102- }
103- int num = v_axes.size();
104- std::vector<int64_t> dims = {};
105- if (num != 0) {
106- dims.push_back(num);
107- }
108- axes = Vec2Tensor(v_axes, dims, ge::DT_INT64);
109- }
110- 
111 auto data1 = op::Const((ori_name + "_data1").c_str()).set_attr_value(axes);80 auto data1 = op::Const((ori_name + "_data1").c_str()).set_attr_value(axes);
112 auto reducemin = op::ReduceMin((ori_name + "_ReduceMin").c_str()).set_input_x(data0).set_input_axes(data1);81 auto reducemin = op::ReduceMin((ori_name + "_ReduceMin").c_str()).set_input_x(data0).set_input_axes(data1);
113 82 
@@ -118,6 +87,13 @@ static Status ParseOpToGraphReduceMin(const ge::Operator& op, Graph& graph)
118 }87 }
119 reducemin.set_attr_keep_dims(keep_dims);88 reducemin.set_attr_keep_dims(keep_dims);
120 89 
90+ int noop_with_empty_axes = 0;
91+ if (op.GetAttr("noop_with_empty_axes", noop_with_empty_axes) != SUCCESS) {
92+ OP_LOGE(GetOpName(op).c_str(), "get noop_with_empty_axes from op failed");
93+ return FAILED;
94+ }
95+ reducemin.set_attr_noop_with_empty_axes(noop_with_empty_axes);
96+ 
121 std::vector<ge::Operator> inputs{data0};97 std::vector<ge::Operator> inputs{data0};
122 std::vector<std::pair<ge::Operator, std::vector<size_t> > > outputs;98 std::vector<std::pair<ge::Operator, std::vector<size_t> > > outputs;
123 outputs.emplace_back(reducemin, std::vector<std::size_t>{0});99 outputs.emplace_back(reducemin, std::vector<std::size_t>{0});
@@ -146,6 +122,14 @@ static Status ParseParamsReduceMin13(const Message* op_src, ge::Operator& op_des
146 }122 }
147 }123 }
148 124 
125+ // opset 13+: axes changed from attribute to input.
126+ // When input_size == 1, there is no axes input; store an empty axes tensor
127+ // so ParseOpToGraph can retrieve it via GetAttr and pass to Const.
128+ std::vector<int> axes = {};
129+ std::vector<int64_t> dims = {0};
130+ ge::Tensor axes_tensor = Vec2Tensor(axes, dims, ge::DT_INT32, ge::FORMAT_NCHW);
131+ op_dest.SetAttr("axes", axes_tensor);
132+ 
149 op_dest.SetAttr("name", node->name());133 op_dest.SetAttr("name", node->name());
150 op_dest.SetAttr("input_size", input_size);134 op_dest.SetAttr("input_size", input_size);
151 op_dest.SetAttr("keep_dims", keep_dims);135 op_dest.SetAttr("keep_dims", keep_dims);
@@ -195,31 +179,20 @@ static Status ParseOpToGraphReduceMin13(const Operator& op, Graph& graph)
195 }179 }
196 auto data0 = op::Data((prop.ori_name + "_data0").c_str()).set_attr_index(0);180 auto data0 = op::Data((prop.ori_name + "_data0").c_str()).set_attr_index(0);
197 int num_input = 2;181 int num_input = 2;
198- if (prop.input_num == 1 && prop.empty_axes == 0) {182+ if (prop.input_num == 1) {
199- int64_t input_dim_num = 0;183+ ge::Tensor axes;
200- if (GetInputTensorDimNum(op, input_dim_num) != SUCCESS) {184+ if (op.GetAttr("axes", axes) != SUCCESS) {
201- OP_LOGE(GetOpName(op).c_str(), "Failed to get input tensor dimensions");185+ OP_LOGE(GetOpName(op).c_str(), "get axes from op failed");
202 return FAILED;186 return FAILED;
203 }187 }
204- 188+ auto data1 = op::Const((prop.ori_name + "_data1").c_str()).set_attr_value(axes);
205- std::vector<int64_t> v_axes;
206- for (int64_t i = 0; i < input_dim_num; ++i) {
207- v_axes.push_back(i);
208- }
209- ge::TensorDesc tensorDesc;
210- std::vector<int64_t> dims = {input_dim_num};
211- ge::Shape shape(dims);
212- tensorDesc.SetShape(shape);
213- tensorDesc.SetDataType(DT_INT64);
214- ge::Tensor tensor(tensorDesc, reinterpret_cast<uint8_t*>(v_axes.data()), v_axes.size() * sizeof(int64_t));
215- auto axes = op::Const((prop.ori_name + "_axes").c_str()).set_attr_value(tensor);
216- std::vector<Operator> inputs{data0, axes};
217- std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;
218 auto reducemin = op::ReduceMin((prop.ori_name + "_ReduceMin").c_str())189 auto reducemin = op::ReduceMin((prop.ori_name + "_ReduceMin").c_str())
219 .set_input_x(data0)190 .set_input_x(data0)
220- .set_input_axes(axes)191+ .set_input_axes(data1)
221 .set_attr_keep_dims(prop.keep_dims)192 .set_attr_keep_dims(prop.keep_dims)
222 .set_attr_noop_with_empty_axes(prop.empty_axes);193 .set_attr_noop_with_empty_axes(prop.empty_axes);
194+ std::vector<Operator> inputs{data0};
195+ std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;
223 output_indexs.emplace_back(reducemin, vector<std::size_t>{0});196 output_indexs.emplace_back(reducemin, vector<std::size_t>{0});
224 graph.SetInputs(inputs).SetOutputs(output_indexs);197 graph.SetInputs(inputs).SetOutputs(output_indexs);
225 } else if (prop.input_num == num_input) {198 } else if (prop.input_num == num_input) {
Mmath/reduce_prod/framework/reduce_prod_onnx_plugin.cpp+24-51
@@ -17,20 +17,6 @@ using ge::Operator;
17namespace domi {17namespace domi {
18using NodeProto = ge::onnx::NodeProto;18using NodeProto = ge::onnx::NodeProto;
19 19 
20-static Status GetInputTensorDimNum(const Operator& data_op, int64_t& dim_num)
21-{
22- ge::TensorDesc input_desc = data_op.GetInputDesc(0);
23- auto shape = input_desc.GetShape();
24- if (shape.GetDimNum() <= 0) {
25- OP_LOGE("GetInputTensorDimNum", "Get input shape is invalid.");
26- return FAILED;
27- }
28- 
29- dim_num = shape.GetDimNum();
30- OP_LOGI(GetOpName(data_op).c_str(), "GetInputTensorDimNum is: %ld", dim_num);
31- return SUCCESS;
32-}
33- 
34static Status ParseParamsReduceProd(const Message* op_src, ge::Operator& op_dest)20static Status ParseParamsReduceProd(const Message* op_src, ge::Operator& op_dest)
35{21{
36 const NodeProto* node = dynamic_cast<const NodeProto*>(op_src);22 const NodeProto* node = dynamic_cast<const NodeProto*>(op_src);
@@ -65,6 +51,7 @@ static Status ParseParamsReduceProd(const Message* op_src, ge::Operator& op_dest
65 op_dest.SetAttr("name", node->name());51 op_dest.SetAttr("name", node->name());
66 op_dest.SetAttr("axes", tensor);52 op_dest.SetAttr("axes", tensor);
67 op_dest.SetAttr("keep_dims", keep_dims);53 op_dest.SetAttr("keep_dims", keep_dims);
54+ op_dest.SetAttr("noop_with_empty_axes", 0);
68 const int input = 2;55 const int input = 2;
69 const int output = 1;56 const int output = 1;
70 op_dest.DynamicInputRegister("x", input);57 op_dest.DynamicInputRegister("x", input);
@@ -90,24 +77,6 @@ static Status ParseOpToGraphReduceProd(const ge::Operator& op, Graph& graph)
90 return FAILED;77 return FAILED;
91 }78 }
92 79 
93- if (axes.GetSize() == 0) {
94- int64_t input_dim_num = 0;
95- if (GetInputTensorDimNum(op, input_dim_num) != SUCCESS) {
96- OP_LOGE(GetOpName(op).c_str(), "Failed to get input tensor dimensions");
97- return FAILED;
98- }
99- std::vector<int64_t> v_axes;
100- for (int64_t i = 0; i < input_dim_num; ++i) {
101- v_axes.push_back(i);
102- }
103- int num = v_axes.size();
104- std::vector<int64_t> dims = {};
105- if (num != 0) {
106- dims.push_back(num);
107- }
108- axes = Vec2Tensor(v_axes, dims, ge::DT_INT64);
109- }
110- 
111 auto data1 = op::Const((ori_name + "_data1").c_str()).set_attr_value(axes);80 auto data1 = op::Const((ori_name + "_data1").c_str()).set_attr_value(axes);
112 auto reduceprod = op::ReduceProd((ori_name + "_ReduceProd").c_str()).set_input_x(data0).set_input_axes(data1);81 auto reduceprod = op::ReduceProd((ori_name + "_ReduceProd").c_str()).set_input_x(data0).set_input_axes(data1);
113 82 
@@ -118,6 +87,13 @@ static Status ParseOpToGraphReduceProd(const ge::Operator& op, Graph& graph)
118 }87 }
119 reduceprod.set_attr_keep_dims(keep_dims);88 reduceprod.set_attr_keep_dims(keep_dims);
120 89 
90+ int noop_with_empty_axes = 0;
91+ if (op.GetAttr("noop_with_empty_axes", noop_with_empty_axes) != SUCCESS) {
92+ OP_LOGE(GetOpName(op).c_str(), "get noop_with_empty_axes from op failed");
93+ return FAILED;
94+ }
95+ reduceprod.set_attr_noop_with_empty_axes(noop_with_empty_axes);
96+ 
121 std::vector<ge::Operator> inputs{data0};97 std::vector<ge::Operator> inputs{data0};
122 std::vector<std::pair<ge::Operator, std::vector<size_t> > > outputs;98 std::vector<std::pair<ge::Operator, std::vector<size_t> > > outputs;
123 outputs.emplace_back(reduceprod, std::vector<std::size_t>{0});99 outputs.emplace_back(reduceprod, std::vector<std::size_t>{0});
@@ -146,6 +122,14 @@ static Status ParseParamsReduceProd13(const Message* op_src, ge::Operator& op_de
146 }122 }
147 }123 }
148 124 
125+ // opset 13+: axes changed from attribute to input.
126+ // When input_size == 1, there is no axes input; store an empty axes tensor
127+ // so ParseOpToGraph can retrieve it via GetAttr and pass to Const.
128+ std::vector<int> axes = {};
129+ std::vector<int64_t> dims = {0};
130+ ge::Tensor axes_tensor = Vec2Tensor(axes, dims, ge::DT_INT32, ge::FORMAT_NCHW);
131+ op_dest.SetAttr("axes", axes_tensor);
132+ 
149 op_dest.SetAttr("name", node->name());133 op_dest.SetAttr("name", node->name());
150 op_dest.SetAttr("input_size", input_size);134 op_dest.SetAttr("input_size", input_size);
151 op_dest.SetAttr("keep_dims", keep_dims);135 op_dest.SetAttr("keep_dims", keep_dims);
@@ -195,31 +179,20 @@ static Status ParseOpToGraphReduceProd13(const Operator& op, Graph& graph)
195 }179 }
196 auto data0 = op::Data((prop.ori_name + "_data0").c_str()).set_attr_index(0);180 auto data0 = op::Data((prop.ori_name + "_data0").c_str()).set_attr_index(0);
197 int num_input = 2;181 int num_input = 2;
198- if (prop.input_num == 1 && prop.empty_axes == 0) {182+ if (prop.input_num == 1) {
199- int64_t input_dim_num = 0;183+ ge::Tensor axes;
200- if (GetInputTensorDimNum(op, input_dim_num) != SUCCESS) {184+ if (op.GetAttr("axes", axes) != SUCCESS) {
201- OP_LOGE(GetOpName(op).c_str(), "Failed to get input tensor dimensions");185+ OP_LOGE(GetOpName(op).c_str(), "get axes from op failed");
202 return FAILED;186 return FAILED;
203 }187 }
204- 188+ auto data1 = op::Const((prop.ori_name + "_data1").c_str()).set_attr_value(axes);
205- std::vector<int64_t> v_axes;
206- for (int64_t i = 0; i < input_dim_num; ++i) {
207- v_axes.push_back(i);
208- }
209- ge::TensorDesc tensorDesc;
210- std::vector<int64_t> dims = {input_dim_num};
211- ge::Shape shape(dims);
212- tensorDesc.SetShape(shape);
213- tensorDesc.SetDataType(DT_INT64);
214- ge::Tensor tensor(tensorDesc, reinterpret_cast<uint8_t*>(v_axes.data()), v_axes.size() * sizeof(int64_t));
215- auto axes = op::Const((prop.ori_name + "_axes").c_str()).set_attr_value(tensor);
216- std::vector<Operator> inputs{data0, axes};
217- std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;
218 auto reduceprod = op::ReduceProd((prop.ori_name + "_ReduceProd").c_str())189 auto reduceprod = op::ReduceProd((prop.ori_name + "_ReduceProd").c_str())
219 .set_input_x(data0)190 .set_input_x(data0)
220- .set_input_axes(axes)191+ .set_input_axes(data1)
221 .set_attr_keep_dims(prop.keep_dims)192 .set_attr_keep_dims(prop.keep_dims)
222 .set_attr_noop_with_empty_axes(prop.empty_axes);193 .set_attr_noop_with_empty_axes(prop.empty_axes);
194+ std::vector<Operator> inputs{data0};
195+ std::vector<std::pair<Operator, std::vector<size_t> > > output_indexs;
223 output_indexs.emplace_back(reduceprod, vector<std::size_t>{0});196 output_indexs.emplace_back(reduceprod, vector<std::size_t>{0});
224 graph.SetInputs(inputs).SetOutputs(output_indexs);197 graph.SetInputs(inputs).SetOutputs(output_indexs);
225 } else if (prop.input_num == num_input) {198 } else if (prop.input_num == num_input) {