From e7243d9d72a3d99b2256ded587a6282c9a385688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Fri, 18 Aug 2023 07:15:31 +0000 Subject: [PATCH 01/25] Implement parsing support for onnx opset 18 versions of reduce operators --- src/include/migraphx/op/reduce_op.hpp | 6 ++- src/onnx/parse_reduce_op.cpp | 74 +++++++++++++++------------ 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 23243b6e31e..3f6a4a64074 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -80,11 +80,15 @@ template struct reduce_op : op_name { std::vector axes{}; + bool runtime_axes = false; + bool noop_with_empty_axes = false; template static auto reflect(Self& self, F f) { - return pack(f(self.axes, "axes")); + return pack(f(self.axes, "axes"), + f(self.runtime_axes, "runtime_axes"), + f(self.noop_with_empty_axes, "noop_with_empty_axes")); } value attributes() const diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index 3cfbce0fab8..9dd9f975ac8 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -31,6 +31,19 @@ namespace migraphx { inline namespace MIGRAPHX_INLINE_NS { namespace onnx { +template +static std::optional parse_attribute(const std::string& attribute_name, + const onnx_parser& parser, + onnx_parser::node_info& info) +{ + if(!contains(info.attributes, attribute_name)) + { + return std::nullopt; + } + + return parser.parse_value(info.attributes.at(attribute_name)).at(); +} + instruction_ref parse_reduce_oper(const std::string& op_name, const onnx_parser& parser, onnx_parser::node_info info, @@ -38,56 +51,53 @@ instruction_ref parse_reduce_oper(const std::string& op_name, { // default to reduce over all dimensions std::vector axes; + bool runtime_axes = false; if(args.size() == 2) { - auto arg_axes = args.at(1)->eval(); - check_arg_empty(arg_axes, "PARSE_" + op_name + ": cannot handle variable axes!"); - axes.clear(); - arg_axes.visit([&](auto s) { axes.assign(s.begin(), s.end()); }); + if(!(runtime_axes = !args[1]->can_eval())) + { + args[1]->eval().visit([&](auto s) { axes.assign(s.begin(), s.end()); }); + } } else if(contains(info.attributes, "axes")) { - axes.clear(); auto&& attr_axes = info.attributes["axes"].ints(); - axes = std::vector(attr_axes.begin(), attr_axes.end()); - } - - bool noop_with_empty_axes = false; - if(contains(info.attributes, "noop_with_empty_axes")) - { - noop_with_empty_axes = static_cast( - parser.parse_value(info.attributes.at("noop_with_empty_axes")).at()); + axes.assign(attr_axes.begin(), attr_axes.end()); } + bool noop_with_empty_axes = + parse_attribute("noop_with_empty_axes", parser, info).value_or(0); // empty axes behavior - if(axes.empty()) + if(axes.empty() && !runtime_axes) { if(noop_with_empty_axes) { - return args.at(0); + return args[0]; } - else - { - axes.resize(args.front()->get_shape().ndim()); - std::iota(axes.begin(), axes.end(), 0); - } - } - int keep_dims = 1; - if(contains(info.attributes, "keepdims")) - { - keep_dims = parser.parse_value(info.attributes.at("keepdims")).at(); + axes.resize(args.front()->get_shape().ndim()); + std::iota(axes.begin(), axes.end(), 0); } - if(keep_dims == 1) - { - return info.add_instruction(make_op(op_name, {{"axes", axes}}), args.front()); - } - else + bool keep_dims = parse_attribute("keepdims", parser, info).value_or(1); + + auto reduce_op = make_op(op_name, + {{"axes", axes}, + {"runtime_axes", runtime_axes}, + {"noop_with_empty_axes", noop_with_empty_axes}}); + auto return_instruction = runtime_axes ? info.add_instruction(reduce_op, args) + : info.add_instruction(reduce_op, args[0]); + if(!keep_dims) { - auto ins = info.add_instruction(make_op(op_name, {{"axes", axes}}), args.front()); - return info.add_instruction(make_op("squeeze", {{"axes", axes}}), ins); + if(runtime_axes) + { + MIGRAPHX_THROW("Keepdims currently not supported with runtime provided axes"); + } + return_instruction = + info.add_instruction(make_op("squeeze", {{"axes", axes}}), return_instruction); } + + return return_instruction; } struct parse_reduce_op : op_parser From 714b10e48894e67c2d98c9bc18511e9cdfca1c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Sat, 19 Aug 2023 08:28:00 +0000 Subject: [PATCH 02/25] Implement codepath for handling a static data shape for reduce operators --- src/include/migraphx/op/reduce_op.hpp | 115 ++++++++++++++++++-------- src/onnx/parse_reduce_op.cpp | 6 +- 2 files changed, 84 insertions(+), 37 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 3f6a4a64074..28f5e1b280a 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -80,15 +80,12 @@ template struct reduce_op : op_name { std::vector axes{}; - bool runtime_axes = false; bool noop_with_empty_axes = false; template static auto reflect(Self& self, F f) { - return pack(f(self.axes, "axes"), - f(self.runtime_axes, "runtime_axes"), - f(self.noop_with_empty_axes, "noop_with_empty_axes")); + return pack(f(self.axes, "axes"), f(self.noop_with_empty_axes, "noop_with_empty_axes")); } value attributes() const @@ -110,6 +107,44 @@ struct reduce_op : op_name return tuned_axes; } + shape compute_dynamic_shape(const std::vector& inputs) const + { + // TODO + // auto data_shape = inputs.at(0); + // auto output_dyn_dims = data_shape.dyn_dims(); + // auto tuned_axes = tune_axes(output_dyn_dims.size()); + // for(const auto& axis : tuned_axes) + // { + // output_dyn_dims[axis] = {1, 1}; + // } + + // return shape{data_shape.type(), output_dyn_dims}; + } + + shape compute_static_shape(const std::vector& inputs) const + { + auto data_shape = inputs.at(0); + auto lens = data_shape.lens(); + if(axes.empty()) + { + std::vector dims(data_shape.ndim()); + std::transform(lens.begin(), lens.end(), dims.begin(), [](auto l) { + return shape::dynamic_dimension{1, l}; + }); + + return shape(data_shape.type(), std::move(dims)); + } + else + { + for(const auto a : axes) + { + lens[a] = 1; + } + + return data_shape.with_lens(lens); + } + } + /** * @brief returns a shape in which the axis or axes named * for reduction by this op are set, to size 1. @@ -119,29 +154,16 @@ struct reduce_op : op_name */ shape normalize_compute_shape(std::vector inputs) const { - check_shapes{inputs, *this, true}.has(1); - auto s = inputs.at(0); - if(s.dynamic()) - { - auto output_dyn_dims = s.dyn_dims(); - auto tuned_axes = tune_axes(output_dyn_dims.size()); - for(const auto& axis : tuned_axes) - { - output_dyn_dims[axis] = {1, 1}; - } + auto expected_arg_count = axes.empty() ? 2 : 1; + check_shapes{inputs, *this, true}.has(expected_arg_count); - return shape{s.type(), output_dyn_dims}; + if(inputs[0].dynamic()) + { + return compute_dynamic_shape(inputs); } else { - auto lens = s.lens(); - auto tuned_axes = tune_axes(lens.size()); - for(const auto& axis : tuned_axes) - { - lens[axis] = 1; - } - - return inputs[0].with_lens(lens); + return compute_static_shape(inputs); } } @@ -179,16 +201,43 @@ struct reduce_op : op_name argument compute(const dyn_output& dyn_out, std::vector args) const { - argument result{dyn_out.computed_shape}; - auto arg_lens = args.front().get_shape().lens(); - auto tuned_axes = tune_axes(arg_lens.size()); - std::vector batch_lens(dyn_out.computed_shape.lens().size(), 1); - tune_dims(tuned_axes, arg_lens, batch_lens); - shape batch_shape{dyn_out.computed_shape.type(), batch_lens}; - visit_all(result, args[0])([&](auto output, auto input) { - par_for(dyn_out.computed_shape.elements(), [&](auto i) { - auto out_idx = dyn_out.computed_shape.multi(i); - this->reduce(input, batch_shape, tuned_axes, out_idx, output); + std::vector reduce_axes; + if(axes.empty()) + { + args[1].visit([&](auto&& s) { reduce_axes.assign(s.begin(), s.end()); }); + } + else + { + reduce_axes = axes; + } + + auto&& data_arg = args[0]; + if(reduce_axes.empty()) + { + if(noop_with_empty_axes) + { + return data_arg; + } + + reduce_axes.resize(data_arg.get_shape().ndim()); + std::iota(reduce_axes.begin(), reduce_axes.end(), 0); + } + + auto arg_lens = data_arg.get_shape().lens(); + for(auto a : reduce_axes) + { + arg_lens[a] = 1; + } + auto result_shape = data_arg.get_shape().with_lens(arg_lens); + + std::vector batch_lens(result_shape.ndim(), 1); + tune_dims(reduce_axes, arg_lens, batch_lens); + shape batch_shape{result_shape.type(), batch_lens}; + argument result{result_shape}; + visit_all(result, data_arg)([&](auto output, auto input) { + par_for(result_shape.elements(), [&](auto i) { + auto out_idx = result_shape.multi(i); + this->reduce(input, batch_shape, reduce_axes, out_idx, output); }); }); diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index 9dd9f975ac8..cfa876fe1e3 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -81,10 +81,8 @@ instruction_ref parse_reduce_oper(const std::string& op_name, bool keep_dims = parse_attribute("keepdims", parser, info).value_or(1); - auto reduce_op = make_op(op_name, - {{"axes", axes}, - {"runtime_axes", runtime_axes}, - {"noop_with_empty_axes", noop_with_empty_axes}}); + auto reduce_op = + make_op(op_name, {{"axes", axes}, {"noop_with_empty_axes", noop_with_empty_axes}}); auto return_instruction = runtime_axes ? info.add_instruction(reduce_op, args) : info.add_instruction(reduce_op, args[0]); if(!keep_dims) From ae024f2d90b59903fc2c6853f45aaadd66b264a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Sat, 19 Aug 2023 10:38:03 +0000 Subject: [PATCH 03/25] Implement dynamic shape computation and refactor existing code --- src/include/migraphx/op/reduce_op.hpp | 112 ++++++++++++++------------ 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 28f5e1b280a..6d6c7dc619e 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -95,39 +95,47 @@ struct reduce_op : op_name return {{"normalize_axes", normalize}, {"reduce", true}}; } - std::vector tune_axes(std::size_t n_dim) const + shape collapse_reduced_axes(const shape& original_shape, + const std::vector& reduce_axes) const { - auto tuned_axes = axes; - if(tuned_axes.empty()) + auto lens = original_shape.lens(); + for(const auto a : reduce_axes) { - tuned_axes.resize(n_dim); - std::iota(tuned_axes.begin(), tuned_axes.end(), 0); + lens[a] = 1; } - return tuned_axes; + return original_shape.with_lens(lens); } shape compute_dynamic_shape(const std::vector& inputs) const { - // TODO - // auto data_shape = inputs.at(0); - // auto output_dyn_dims = data_shape.dyn_dims(); - // auto tuned_axes = tune_axes(output_dyn_dims.size()); - // for(const auto& axis : tuned_axes) - // { - // output_dyn_dims[axis] = {1, 1}; - // } - - // return shape{data_shape.type(), output_dyn_dims}; + auto data_shape = inputs[0]; + auto dims = data_shape.dyn_dims(); + if(axes.empty()) + { + for(auto& dim : dims) + { + dim = {1, dim.max}; + } + } + else + { + for(auto a : axes) + { + dims[a] = {1, 1}; + } + } + + return shape{data_shape.type(), dims}; } shape compute_static_shape(const std::vector& inputs) const { - auto data_shape = inputs.at(0); - auto lens = data_shape.lens(); + auto data_shape = inputs[0]; if(axes.empty()) { std::vector dims(data_shape.ndim()); + auto lens = data_shape.lens(); std::transform(lens.begin(), lens.end(), dims.begin(), [](auto l) { return shape::dynamic_dimension{1, l}; }); @@ -136,12 +144,7 @@ struct reduce_op : op_name } else { - for(const auto a : axes) - { - lens[a] = 1; - } - - return data_shape.with_lens(lens); + return collapse_reduced_axes(data_shape, axes); } } @@ -179,10 +182,10 @@ struct reduce_op : op_name } template - void reduce(tensor_view& input, - shape& batch_shape, - std::vector& tuned_axes, - std::vector& out_idx, + void reduce(const tensor_view& input, + const shape& batch_shape, + const std::vector& tuned_axes, + const std::vector& out_idx, tensor_view& output) const { using accumulator = accumulator_type; @@ -199,19 +202,40 @@ struct reduce_op : op_name static_cast(*this).output(batch_shape)(val); } + argument compute(const shape& computed_shape, + const std::vector& reduce_axes, + argument& data_arg) const + { + std::vector batch_lens(computed_shape.ndim(), 1); + auto arg_lens = data_arg.get_shape().lens(); + tune_dims(reduce_axes, arg_lens, batch_lens); + shape batch_shape{computed_shape.type(), batch_lens}; + argument result{computed_shape}; + + visit_all(result, data_arg)([&](auto output, auto input) { + par_for(computed_shape.elements(), [&](auto i) { + auto out_idx = computed_shape.multi(i); + this->reduce(input, batch_shape, reduce_axes, out_idx, output); + }); + }); + + return result; + } + argument compute(const dyn_output& dyn_out, std::vector args) const { - std::vector reduce_axes; - if(axes.empty()) + auto&& data_arg = args[0]; + if(!axes.empty()) { - args[1].visit([&](auto&& s) { reduce_axes.assign(s.begin(), s.end()); }); + return compute(dyn_out.computed_shape, axes, data_arg); } - else + + std::vector reduce_axes; + if(args.size() == 2) { - reduce_axes = axes; + args[1].visit([&](auto&& s) { reduce_axes.assign(s.begin(), s.end()); }); } - auto&& data_arg = args[0]; if(reduce_axes.empty()) { if(noop_with_empty_axes) @@ -223,25 +247,9 @@ struct reduce_op : op_name std::iota(reduce_axes.begin(), reduce_axes.end(), 0); } - auto arg_lens = data_arg.get_shape().lens(); - for(auto a : reduce_axes) - { - arg_lens[a] = 1; - } - auto result_shape = data_arg.get_shape().with_lens(arg_lens); + const auto result_shape = collapse_reduced_axes(data_arg.get_shape(), reduce_axes); - std::vector batch_lens(result_shape.ndim(), 1); - tune_dims(reduce_axes, arg_lens, batch_lens); - shape batch_shape{result_shape.type(), batch_lens}; - argument result{result_shape}; - visit_all(result, data_arg)([&](auto output, auto input) { - par_for(result_shape.elements(), [&](auto i) { - auto out_idx = result_shape.multi(i); - this->reduce(input, batch_shape, reduce_axes, out_idx, output); - }); - }); - - return result; + return compute(result_shape, reduce_axes, data_arg); } auto init() const { return zero(); } From 904de2ad8682961a8f2c1090c9c277b0a3cbb63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 23 Aug 2023 11:14:11 +0000 Subject: [PATCH 04/25] Add reference operator tests for ReduceMin, ReduceMax, and ReduceMean --- test/ref_ops_test.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/test/ref_ops_test.cpp b/test/ref_ops_test.cpp index 24314be30ac..8adbe20a0dd 100644 --- a/test/ref_ops_test.cpp +++ b/test/ref_ops_test.cpp @@ -6564,6 +6564,54 @@ TEST_CASE(reduce_max_axis02) EXPECT(results_vector == gold); } +template +void reduce_op_axes_input_test(const std::string op_name, + std::vector axes, + std::vector gold) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + auto data_static_shape = migraphx::shape{migraphx::shape::get_type{}, {3, 2, 2}}; + auto data_shape = dynamic ? migraphx::shape{migraphx::shape::get_type{}, + {{2, 5, {}}, {2, 3, {}}, {2, 3, {}}}} + : data_static_shape; + auto data_param = mm->add_parameter("data", data_shape); + auto axes_shape = migraphx::shape{migraphx::shape::int64_type, {axes.size()}}; + auto axes_param = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op(op_name, {}), data_param, axes_param); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map params; + T data[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + params["data"] = migraphx::argument(data_static_shape, data); + params["axes"] = migraphx::argument(axes_shape, axes.data()); + auto result = p.eval(params).back(); + + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + EXPECT(results_vector == gold); +} + +TEST_CASE(reduce_max_axes_input_axis0) +{ + reduce_op_axes_input_test("reduce_max", {0}, {9, 10, 11, 12}); +} + +TEST_CASE(reduce_max_axes_input_axes01) +{ + reduce_op_axes_input_test("reduce_max", {0, 1}, {11, 12}); +} + +TEST_CASE(reduce_max_axes_input_axes02) +{ + reduce_op_axes_input_test("reduce_max", {0, 2}, {10, 12}); +} + +TEST_CASE(reduce_max_dynamic_data_axes_input_axis0) +{ + reduce_op_axes_input_test("reduce_max", {0}, {9, 10, 11, 12}); +} + TEST_CASE(reduce_mean_axis02) { migraphx::program p; @@ -6644,6 +6692,31 @@ TEST_CASE(reduce_mean_int) EXPECT(results_vector == gold); } +TEST_CASE(reduce_mean_axes_input_axes02) +{ + reduce_op_axes_input_test("reduce_mean", {0, 2}, {5.5f, 7.5f}); +} + +TEST_CASE(reduce_mean_axes_input_axis1) +{ + reduce_op_axes_input_test("reduce_mean", {1}, {2, 3, 6, 7, 10, 11}); +} + +TEST_CASE(reduce_mean_axes_input_axes12) +{ + reduce_op_axes_input_test("reduce_mean", {1, 2}, {2.5f, 6.5f, 10.5f}); +} + +TEST_CASE(reduce_mean_axes_input_axis2) +{ + reduce_op_axes_input_test("reduce_mean", {2}, {1.5f, 3.5f, 5.5f, 7.5f, 9.5f, 11.5f}); +} + +TEST_CASE(reduce_mean_int_axes_input_axes12) +{ + reduce_op_axes_input_test("reduce_mean", {1, 2}, {2, 6, 10}); +} + TEST_CASE(reduce_min_axis02) { migraphx::program p; @@ -6692,6 +6765,21 @@ TEST_CASE(reduce_min_axis12) EXPECT(results_vector == gold); } +TEST_CASE(reduce_min_axes_input_axes02) +{ + reduce_op_axes_input_test("reduce_min", {0, 2}, {1, 3}); +} + +TEST_CASE(reduce_min_axes_input_axis1) +{ + reduce_op_axes_input_test("reduce_min", {1}, {1, 2, 5, 6, 9, 10}); +} + +TEST_CASE(reduce_min_axes_input_axes12) +{ + reduce_op_axes_input_test("reduce_min", {1, 2}, {1, 5, 9}); +} + TEST_CASE(reduce_prod_axis0) { migraphx::program p; From 4316e48aac92b7393aeff8b11583874fa5c94be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Thu, 31 Aug 2023 09:23:45 +0000 Subject: [PATCH 05/25] Disable failing onnx backend tests --- test/py/onnx_backend_test.py | 84 ++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test/py/onnx_backend_test.py b/test/py/onnx_backend_test.py index 4ae7203b6da..ae58118481f 100644 --- a/test/py/onnx_backend_test.py +++ b/test/py/onnx_backend_test.py @@ -108,6 +108,87 @@ def disabled_tests_onnx_1_12_0(backend_test): backend_test.exclude(r'test_scatter_elements_with_duplicate_indices_cpu') +def disabled_tests_onnx_1_13_0(backend_test): + # The following reduce tests are disabled owing to a general lack of support in the backends + # for operators whose output shape depends on a variable input, + # specifically for reductions, variable axes. + # ReduceL1 + backend_test.exclude(r'test_reduce_l1_default_axes_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_l1_default_axes_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_l1_do_not_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_l1_do_not_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_l1_keep_dims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_l1_keep_dims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_l1_negative_axes_keep_dims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_l1_negative_axes_keep_dims_random_expanded_cpu') + # ReduceL2 + backend_test.exclude(r'test_reduce_l2_default_axes_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_l2_default_axes_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_l2_do_not_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_l2_do_not_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_l2_keep_dims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_l2_keep_dims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_l2_negative_axes_keep_dims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_l2_negative_axes_keep_dims_random_expanded_cpu') + # ReduceLogSum + backend_test.exclude(r'test_reduce_log_sum_asc_axes_cpu') + backend_test.exclude(r'test_reduce_log_sum_asc_axes_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_default_cpu') + backend_test.exclude(r'test_reduce_log_sum_default_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_desc_axes_cpu') + backend_test.exclude(r'test_reduce_log_sum_desc_axes_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_negative_axes_cpu') + backend_test.exclude(r'test_reduce_log_sum_negative_axes_expanded_cpu') + # ReduceLogSumExp + backend_test.exclude(r'test_reduce_log_sum_exp_default_axes_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_exp_default_axes_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_exp_do_not_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_exp_do_not_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_exp_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_exp_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_exp_negative_axes_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_log_sum_exp_negative_axes_keepdims_random_expanded_cpu') + # ReduceMax + backend_test.exclude(r'test_reduce_max_do_not_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_max_do_not_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_max_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_max_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_max_negative_axes_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_max_negative_axes_keepdims_random_cpu') + # ReduceMean + backend_test.exclude(r'test_reduce_mean_default_axes_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_mean_default_axes_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_mean_do_not_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_mean_do_not_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_mean_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_mean_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_mean_negative_axes_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_mean_negative_axes_keepdims_random_cpu') + #ReduceMin + backend_test.exclude(r'test_reduce_min_do_not_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_min_do_not_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_min_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_min_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_min_negative_axes_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_min_negative_axes_keepdims_random_cpu') + #ReduceProd + backend_test.exclude(r'test_reduce_prod_do_not_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_prod_do_not_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_prod_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_prod_keepdims_random_cpu') + backend_test.exclude(r'test_reduce_prod_negative_axes_keepdims_example_cpu') + backend_test.exclude(r'test_reduce_prod_negative_axes_keepdims_random_cpu') + #ReduceSumSquare + backend_test.exclude(r'test_reduce_sum_square_default_axes_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_sum_square_default_axes_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_sum_square_do_not_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_sum_square_do_not_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_sum_square_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_sum_square_keepdims_random_expanded_cpu') + backend_test.exclude(r'test_reduce_sum_square_negative_axes_keepdims_example_expanded_cpu') + backend_test.exclude(r'test_reduce_sum_square_negative_axes_keepdims_random_expanded_cpu') + + def create_backend_test(testname=None, target_device=None): if target_device is not None: c2.set_device(target_device) @@ -334,6 +415,9 @@ def create_backend_test(testname=None, target_device=None): if version.parse(onnx.__version__) >= version.parse("1.12.0"): disabled_tests_onnx_1_12_0(backend_test) + if version.parse(onnx.__version__) >= version.parse("1.13.0"): + disabled_tests_onnx_1_13_0(backend_test) + # import all test cases at global scope to make # them visible to python.unittest. From b0244363157cf3331cbbb31c165f1f87781232bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 6 Sep 2023 10:30:19 +0000 Subject: [PATCH 06/25] Remove noop_with_empty_axes_attribute, fix code style issues --- src/include/migraphx/op/reduce_op.hpp | 18 +-- src/onnx/parse_reduce_op.cpp | 19 ++-- test/op_shape_test.cpp | 16 --- test/ref_ops_test.cpp | 156 +++++++++++++------------- 4 files changed, 96 insertions(+), 113 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 6d6c7dc619e..df6dacf3e5f 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -80,12 +80,11 @@ template struct reduce_op : op_name { std::vector axes{}; - bool noop_with_empty_axes = false; template static auto reflect(Self& self, F f) { - return pack(f(self.axes, "axes"), f(self.noop_with_empty_axes, "noop_with_empty_axes")); + return pack(f(self.axes, "axes")); } value attributes() const @@ -109,7 +108,7 @@ struct reduce_op : op_name shape compute_dynamic_shape(const std::vector& inputs) const { - auto data_shape = inputs[0]; + const auto& data_shape = inputs[0]; auto dims = data_shape.dyn_dims(); if(axes.empty()) { @@ -131,7 +130,7 @@ struct reduce_op : op_name shape compute_static_shape(const std::vector& inputs) const { - auto data_shape = inputs[0]; + const auto& data_shape = inputs[0]; if(axes.empty()) { std::vector dims(data_shape.ndim()); @@ -140,7 +139,7 @@ struct reduce_op : op_name return shape::dynamic_dimension{1, l}; }); - return shape(data_shape.type(), std::move(dims)); + return shape{data_shape.type(), std::move(dims)}; } else { @@ -238,13 +237,8 @@ struct reduce_op : op_name if(reduce_axes.empty()) { - if(noop_with_empty_axes) - { - return data_arg; - } - - reduce_axes.resize(data_arg.get_shape().ndim()); - std::iota(reduce_axes.begin(), reduce_axes.end(), 0); + // If axes is empty always treat is a noop + return data_arg; } const auto result_shape = collapse_reduced_axes(data_arg.get_shape(), reduce_axes); diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index cfa876fe1e3..30ada21c7c2 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -54,7 +54,13 @@ instruction_ref parse_reduce_oper(const std::string& op_name, bool runtime_axes = false; if(args.size() == 2) { - if(!(runtime_axes = !args[1]->can_eval())) + runtime_axes = not args[1]->can_eval(); + if(runtime_axes) + { + // The reference implementation supports variable axes, but the backends do not + MIGRAPHX_THROW("Cannot handle variable axes"); + } + else { args[1]->eval().visit([&](auto s) { axes.assign(s.begin(), s.end()); }); } @@ -65,10 +71,10 @@ instruction_ref parse_reduce_oper(const std::string& op_name, axes.assign(attr_axes.begin(), attr_axes.end()); } - bool noop_with_empty_axes = + int noop_with_empty_axes = parse_attribute("noop_with_empty_axes", parser, info).value_or(0); // empty axes behavior - if(axes.empty() && !runtime_axes) + if(axes.empty() and not runtime_axes) { if(noop_with_empty_axes) { @@ -79,13 +85,12 @@ instruction_ref parse_reduce_oper(const std::string& op_name, std::iota(axes.begin(), axes.end(), 0); } - bool keep_dims = parse_attribute("keepdims", parser, info).value_or(1); + int keep_dims = parse_attribute("keepdims", parser, info).value_or(1); - auto reduce_op = - make_op(op_name, {{"axes", axes}, {"noop_with_empty_axes", noop_with_empty_axes}}); + auto reduce_op = make_op(op_name, {{"axes", axes}}); auto return_instruction = runtime_axes ? info.add_instruction(reduce_op, args) : info.add_instruction(reduce_op, args[0]); - if(!keep_dims) + if(not keep_dims) { if(runtime_axes) { diff --git a/test/op_shape_test.cpp b/test/op_shape_test.cpp index cdee089a287..ef145ceabf1 100644 --- a/test/op_shape_test.cpp +++ b/test/op_shape_test.cpp @@ -2340,13 +2340,6 @@ TEST_CASE(dqlinear_mismatch_type) void test_reduce_ops(const std::string& name) { - { - migraphx::shape input{migraphx::shape::float_type, {2, 3, 4, 5}}; - expect_shape(migraphx::shape{migraphx::shape::float_type, {1, 1, 1, 1}}, - migraphx::make_op(name), - input); - } - { migraphx::shape input{migraphx::shape::float_type, {2, 3, 4, 5}}; expect_shape(migraphx::shape{migraphx::shape::float_type, {1, 1, 1, 1}}, @@ -2396,15 +2389,6 @@ void test_dyn_reduce_ops(const std::string& name) migraphx::make_op(name, {{"axes", {0}}}), input); } - { - // Empty axis argument reduces all axes - migraphx::shape input{migraphx::shape::float_type, {{2, 3, {3}}, {2, 4, {4}}}}; - expect_shape( - migraphx::shape{migraphx::shape::float_type, - std::vector({{1, 1}, {1, 1}})}, - migraphx::make_op(name), - input); - } { migraphx::shape input{migraphx::shape::float_type, {{2, 3, {3}}, {2, 4, {4}}}}; throws_shape(migraphx::make_op(name, {{"axes", {4}}}), input); diff --git a/test/ref_ops_test.cpp b/test/ref_ops_test.cpp index 8adbe20a0dd..fe8b53bd7fc 100644 --- a/test/ref_ops_test.cpp +++ b/test/ref_ops_test.cpp @@ -1333,17 +1333,17 @@ TEST_CASE(conv_dyn_weights_shape_test) 0.81217463, 0.10789447, 0.43083784, 0.63371852, 0.69742316, 0.09536905}; std::vector c = {0.98411968, - 0.2899219, - 0.44638833, - 0.30390816, - 0.03989896, - 0.2445332, - 0.32700131, - 0.57517075, - 0.06956476, - 0.93079306, - 0.19882314, - 0.52940601}; + 0.2899219, + 0.44638833, + 0.30390816, + 0.03989896, + 0.2445332, + 0.32700131, + 0.57517075, + 0.06956476, + 0.93079306, + 0.19882314, + 0.52940601}; std::vector sol = {1.9939406, 2.2703054, 1.8896171, @@ -1367,9 +1367,9 @@ TEST_CASE(conv_dyn_weights_shape_test) EXPECT(migraphx::verify::verify_range(results_vector, sol)); c = {0.98411968, 0.2899219, 0.44638833, 0.30390816, 0.03989896, 0.2445332, 0.32700131, - 0.57517075, 0.06956476, 0.93079306, 0.19882314, 0.52940601, 0.35624753, 0.35938406, - 0.9111428, 0.88923574, 0.61040283, 0.2797513, 0.15479768, 0.46534674, 0.16970931, - 0.49704618, 0.07062198, 0.01678321, 0.53150934, 0.39244495, 0.9963813}; + 0.57517075, 0.06956476, 0.93079306, 0.19882314, 0.52940601, 0.35624753, 0.35938406, + 0.9111428, 0.88923574, 0.61040283, 0.2797513, 0.15479768, 0.46534674, 0.16970931, + 0.49704618, 0.07062198, 0.01678321, 0.53150934, 0.39244495, 0.9963813}; sol = {6.1329393, 4.3199925, 5.448438, 3.8497565}; migraphx::shape weights_fixed_shape1{migraphx::shape::float_type, {1, 3, 3, 3}}; @@ -1473,30 +1473,30 @@ TEST_CASE(conv_dyn_kernel_same_upper_test) p.compile(migraphx::make_target("ref")); std::vector a = {0.63321185, 0.6466339, 0.8515352, 0.44240063, 0.5018913, 0.5068494, - 0.75330657, 0.7383877, 0.15870683, 0.8171611, 0.56118083, 0.87004256, - 0.24401724, 0.8815178, 0.4222333, 0.27191755, + 0.75330657, 0.7383877, 0.15870683, 0.8171611, 0.56118083, 0.87004256, + 0.24401724, 0.8815178, 0.4222333, 0.27191755, - 0.41633207, 0.2460619, 0.32004243, 0.6962248, 0.12284133, 0.2620491, - 0.96931046, 0.6030955, 0.7623861, 0.2395751, 0.61440414, 0.577285, - 0.80087787, 0.12776066, 0.26566318, 0.46569306, + 0.41633207, 0.2460619, 0.32004243, 0.6962248, 0.12284133, 0.2620491, + 0.96931046, 0.6030955, 0.7623861, 0.2395751, 0.61440414, 0.577285, + 0.80087787, 0.12776066, 0.26566318, 0.46569306, - 0.96701574, 0.3850145, 0.14165345, 0.5887347, 0.7152134, 0.5295342, - 0.6303507, 0.4037548, 0.18556239, 0.79416305, 0.29107493, 0.18770285, - 0.6870904, 0.30701008, 0.314684, 0.91075855}; + 0.96701574, 0.3850145, 0.14165345, 0.5887347, 0.7152134, 0.5295342, + 0.6303507, 0.4037548, 0.18556239, 0.79416305, 0.29107493, 0.18770285, + 0.6870904, 0.30701008, 0.314684, 0.91075855}; std::vector c = {2.8150102e-01, - 3.3198616e-01, - 9.5149356e-01, - 7.4039467e-02, - - 9.6555042e-01, - 2.8815505e-01, - 2.5100240e-01, - 5.2186239e-01, - - 2.3850012e-01, - 8.2963020e-01, - 3.0763101e-04, - 6.7026985e-01}; + 3.3198616e-01, + 9.5149356e-01, + 7.4039467e-02, + + 9.6555042e-01, + 2.8815505e-01, + 2.5100240e-01, + 5.2186239e-01, + + 2.3850012e-01, + 8.2963020e-01, + 3.0763101e-04, + 6.7026985e-01}; std::vector sol = {2.453681, 2.536207, 3.0187201, @@ -1546,30 +1546,30 @@ TEST_CASE(conv_dyn_kernel_same_lower_test) p.compile(migraphx::make_target("ref")); std::vector a = {0.63321185, 0.6466339, 0.8515352, 0.44240063, 0.5018913, 0.5068494, - 0.75330657, 0.7383877, 0.15870683, 0.8171611, 0.56118083, 0.87004256, - 0.24401724, 0.8815178, 0.4222333, 0.27191755, + 0.75330657, 0.7383877, 0.15870683, 0.8171611, 0.56118083, 0.87004256, + 0.24401724, 0.8815178, 0.4222333, 0.27191755, - 0.41633207, 0.2460619, 0.32004243, 0.6962248, 0.12284133, 0.2620491, - 0.96931046, 0.6030955, 0.7623861, 0.2395751, 0.61440414, 0.577285, - 0.80087787, 0.12776066, 0.26566318, 0.46569306, + 0.41633207, 0.2460619, 0.32004243, 0.6962248, 0.12284133, 0.2620491, + 0.96931046, 0.6030955, 0.7623861, 0.2395751, 0.61440414, 0.577285, + 0.80087787, 0.12776066, 0.26566318, 0.46569306, - 0.96701574, 0.3850145, 0.14165345, 0.5887347, 0.7152134, 0.5295342, - 0.6303507, 0.4037548, 0.18556239, 0.79416305, 0.29107493, 0.18770285, - 0.6870904, 0.30701008, 0.314684, 0.91075855}; + 0.96701574, 0.3850145, 0.14165345, 0.5887347, 0.7152134, 0.5295342, + 0.6303507, 0.4037548, 0.18556239, 0.79416305, 0.29107493, 0.18770285, + 0.6870904, 0.30701008, 0.314684, 0.91075855}; std::vector c = {2.8150102e-01, - 3.3198616e-01, - 9.5149356e-01, - 7.4039467e-02, - - 9.6555042e-01, - 2.8815505e-01, - 2.5100240e-01, - 5.2186239e-01, - - 2.3850012e-01, - 8.2963020e-01, - 3.0763101e-04, - 6.7026985e-01}; + 3.3198616e-01, + 9.5149356e-01, + 7.4039467e-02, + + 9.6555042e-01, + 2.8815505e-01, + 2.5100240e-01, + 5.2186239e-01, + + 2.3850012e-01, + 8.2963020e-01, + 3.0763101e-04, + 6.7026985e-01}; std::vector sol = {0.91231215, 1.1416453, 1.00216, @@ -4039,19 +4039,19 @@ TEST_CASE(imagescaler_test) migraphx::shape s{migraphx::shape::float_type, {1, 3, 2, 2}}; auto img = mm->add_literal(migraphx::literal{s, {0.2, - 0.3, - 0.5, - 0.4, - - 0.7, - 0.8, - 0.1, - 0.9, - - 0.15, - 0.25, - 0.35, - 0.45}}); + 0.3, + 0.5, + 0.4, + + 0.7, + 0.8, + 0.1, + 0.9, + + 0.15, + 0.25, + 0.35, + 0.45}}); auto scale_val = mm->add_literal(2.f); auto scaled_tensor = mm->add_instruction( migraphx::make_op("scalar", {{"scalar_bcst_dims", s.lens()}}), scale_val); @@ -5389,9 +5389,9 @@ TEST_CASE(nms_dyn_batch_test) p.compile(migraphx::make_target("ref")); std::vector boxes_vec = {0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, - 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0, - 0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, - 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}; + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0, + 0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}; std::vector scores_vec = { 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}; @@ -5435,7 +5435,7 @@ TEST_CASE(nms_dyn_boxes_test) p.compile(migraphx::make_target("ref")); std::vector boxes_vec = {0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, - 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}; + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}; std::vector scores_vec = {0.9, 0.75, 0.6, 0.95, 0.5, 0.3}; migraphx::shape input_fixed_shape0{migraphx::shape::float_type, {1, 6, 4}}; @@ -5478,8 +5478,8 @@ TEST_CASE(nms_dyn_classes_test) p.compile(migraphx::make_target("ref")); std::vector boxes_vec = {0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, - 0.0, -0.1, 1.0, 0.9, 0.0, 10.0, 1.0, 11.0, - 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}; + 0.0, -0.1, 1.0, 0.9, 0.0, 10.0, 1.0, 11.0, + 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}; std::vector scores_vec = { 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}; migraphx::shape input_fixed_shape0{migraphx::shape::float_type, {1, 6, 4}}; @@ -6564,15 +6564,15 @@ TEST_CASE(reduce_max_axis02) EXPECT(results_vector == gold); } -template -void reduce_op_axes_input_test(const std::string op_name, +template +void reduce_op_axes_input_test(const std::string& op_name, std::vector axes, std::vector gold) { migraphx::program p; auto* mm = p.get_main_module(); auto data_static_shape = migraphx::shape{migraphx::shape::get_type{}, {3, 2, 2}}; - auto data_shape = dynamic ? migraphx::shape{migraphx::shape::get_type{}, + auto data_shape = Dynamic ? migraphx::shape{migraphx::shape::get_type{}, {{2, 5, {}}, {2, 3, {}}, {2, 3, {}}}} : data_static_shape; auto data_param = mm->add_parameter("data", data_shape); From 5b2f4c354e74060bdc060cac63bc78de83184065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 6 Sep 2023 10:42:04 +0000 Subject: [PATCH 07/25] Restore ref_ops_test.cpp --- test/ref_ops_test.cpp | 156 +++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/test/ref_ops_test.cpp b/test/ref_ops_test.cpp index fe8b53bd7fc..8adbe20a0dd 100644 --- a/test/ref_ops_test.cpp +++ b/test/ref_ops_test.cpp @@ -1333,17 +1333,17 @@ TEST_CASE(conv_dyn_weights_shape_test) 0.81217463, 0.10789447, 0.43083784, 0.63371852, 0.69742316, 0.09536905}; std::vector c = {0.98411968, - 0.2899219, - 0.44638833, - 0.30390816, - 0.03989896, - 0.2445332, - 0.32700131, - 0.57517075, - 0.06956476, - 0.93079306, - 0.19882314, - 0.52940601}; + 0.2899219, + 0.44638833, + 0.30390816, + 0.03989896, + 0.2445332, + 0.32700131, + 0.57517075, + 0.06956476, + 0.93079306, + 0.19882314, + 0.52940601}; std::vector sol = {1.9939406, 2.2703054, 1.8896171, @@ -1367,9 +1367,9 @@ TEST_CASE(conv_dyn_weights_shape_test) EXPECT(migraphx::verify::verify_range(results_vector, sol)); c = {0.98411968, 0.2899219, 0.44638833, 0.30390816, 0.03989896, 0.2445332, 0.32700131, - 0.57517075, 0.06956476, 0.93079306, 0.19882314, 0.52940601, 0.35624753, 0.35938406, - 0.9111428, 0.88923574, 0.61040283, 0.2797513, 0.15479768, 0.46534674, 0.16970931, - 0.49704618, 0.07062198, 0.01678321, 0.53150934, 0.39244495, 0.9963813}; + 0.57517075, 0.06956476, 0.93079306, 0.19882314, 0.52940601, 0.35624753, 0.35938406, + 0.9111428, 0.88923574, 0.61040283, 0.2797513, 0.15479768, 0.46534674, 0.16970931, + 0.49704618, 0.07062198, 0.01678321, 0.53150934, 0.39244495, 0.9963813}; sol = {6.1329393, 4.3199925, 5.448438, 3.8497565}; migraphx::shape weights_fixed_shape1{migraphx::shape::float_type, {1, 3, 3, 3}}; @@ -1473,30 +1473,30 @@ TEST_CASE(conv_dyn_kernel_same_upper_test) p.compile(migraphx::make_target("ref")); std::vector a = {0.63321185, 0.6466339, 0.8515352, 0.44240063, 0.5018913, 0.5068494, - 0.75330657, 0.7383877, 0.15870683, 0.8171611, 0.56118083, 0.87004256, - 0.24401724, 0.8815178, 0.4222333, 0.27191755, + 0.75330657, 0.7383877, 0.15870683, 0.8171611, 0.56118083, 0.87004256, + 0.24401724, 0.8815178, 0.4222333, 0.27191755, - 0.41633207, 0.2460619, 0.32004243, 0.6962248, 0.12284133, 0.2620491, - 0.96931046, 0.6030955, 0.7623861, 0.2395751, 0.61440414, 0.577285, - 0.80087787, 0.12776066, 0.26566318, 0.46569306, + 0.41633207, 0.2460619, 0.32004243, 0.6962248, 0.12284133, 0.2620491, + 0.96931046, 0.6030955, 0.7623861, 0.2395751, 0.61440414, 0.577285, + 0.80087787, 0.12776066, 0.26566318, 0.46569306, - 0.96701574, 0.3850145, 0.14165345, 0.5887347, 0.7152134, 0.5295342, - 0.6303507, 0.4037548, 0.18556239, 0.79416305, 0.29107493, 0.18770285, - 0.6870904, 0.30701008, 0.314684, 0.91075855}; + 0.96701574, 0.3850145, 0.14165345, 0.5887347, 0.7152134, 0.5295342, + 0.6303507, 0.4037548, 0.18556239, 0.79416305, 0.29107493, 0.18770285, + 0.6870904, 0.30701008, 0.314684, 0.91075855}; std::vector c = {2.8150102e-01, - 3.3198616e-01, - 9.5149356e-01, - 7.4039467e-02, - - 9.6555042e-01, - 2.8815505e-01, - 2.5100240e-01, - 5.2186239e-01, - - 2.3850012e-01, - 8.2963020e-01, - 3.0763101e-04, - 6.7026985e-01}; + 3.3198616e-01, + 9.5149356e-01, + 7.4039467e-02, + + 9.6555042e-01, + 2.8815505e-01, + 2.5100240e-01, + 5.2186239e-01, + + 2.3850012e-01, + 8.2963020e-01, + 3.0763101e-04, + 6.7026985e-01}; std::vector sol = {2.453681, 2.536207, 3.0187201, @@ -1546,30 +1546,30 @@ TEST_CASE(conv_dyn_kernel_same_lower_test) p.compile(migraphx::make_target("ref")); std::vector a = {0.63321185, 0.6466339, 0.8515352, 0.44240063, 0.5018913, 0.5068494, - 0.75330657, 0.7383877, 0.15870683, 0.8171611, 0.56118083, 0.87004256, - 0.24401724, 0.8815178, 0.4222333, 0.27191755, + 0.75330657, 0.7383877, 0.15870683, 0.8171611, 0.56118083, 0.87004256, + 0.24401724, 0.8815178, 0.4222333, 0.27191755, - 0.41633207, 0.2460619, 0.32004243, 0.6962248, 0.12284133, 0.2620491, - 0.96931046, 0.6030955, 0.7623861, 0.2395751, 0.61440414, 0.577285, - 0.80087787, 0.12776066, 0.26566318, 0.46569306, + 0.41633207, 0.2460619, 0.32004243, 0.6962248, 0.12284133, 0.2620491, + 0.96931046, 0.6030955, 0.7623861, 0.2395751, 0.61440414, 0.577285, + 0.80087787, 0.12776066, 0.26566318, 0.46569306, - 0.96701574, 0.3850145, 0.14165345, 0.5887347, 0.7152134, 0.5295342, - 0.6303507, 0.4037548, 0.18556239, 0.79416305, 0.29107493, 0.18770285, - 0.6870904, 0.30701008, 0.314684, 0.91075855}; + 0.96701574, 0.3850145, 0.14165345, 0.5887347, 0.7152134, 0.5295342, + 0.6303507, 0.4037548, 0.18556239, 0.79416305, 0.29107493, 0.18770285, + 0.6870904, 0.30701008, 0.314684, 0.91075855}; std::vector c = {2.8150102e-01, - 3.3198616e-01, - 9.5149356e-01, - 7.4039467e-02, - - 9.6555042e-01, - 2.8815505e-01, - 2.5100240e-01, - 5.2186239e-01, - - 2.3850012e-01, - 8.2963020e-01, - 3.0763101e-04, - 6.7026985e-01}; + 3.3198616e-01, + 9.5149356e-01, + 7.4039467e-02, + + 9.6555042e-01, + 2.8815505e-01, + 2.5100240e-01, + 5.2186239e-01, + + 2.3850012e-01, + 8.2963020e-01, + 3.0763101e-04, + 6.7026985e-01}; std::vector sol = {0.91231215, 1.1416453, 1.00216, @@ -4039,19 +4039,19 @@ TEST_CASE(imagescaler_test) migraphx::shape s{migraphx::shape::float_type, {1, 3, 2, 2}}; auto img = mm->add_literal(migraphx::literal{s, {0.2, - 0.3, - 0.5, - 0.4, - - 0.7, - 0.8, - 0.1, - 0.9, - - 0.15, - 0.25, - 0.35, - 0.45}}); + 0.3, + 0.5, + 0.4, + + 0.7, + 0.8, + 0.1, + 0.9, + + 0.15, + 0.25, + 0.35, + 0.45}}); auto scale_val = mm->add_literal(2.f); auto scaled_tensor = mm->add_instruction( migraphx::make_op("scalar", {{"scalar_bcst_dims", s.lens()}}), scale_val); @@ -5389,9 +5389,9 @@ TEST_CASE(nms_dyn_batch_test) p.compile(migraphx::make_target("ref")); std::vector boxes_vec = {0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, - 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0, - 0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, - 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}; + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0, + 0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}; std::vector scores_vec = { 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}; @@ -5435,7 +5435,7 @@ TEST_CASE(nms_dyn_boxes_test) p.compile(migraphx::make_target("ref")); std::vector boxes_vec = {0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, - 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}; + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}; std::vector scores_vec = {0.9, 0.75, 0.6, 0.95, 0.5, 0.3}; migraphx::shape input_fixed_shape0{migraphx::shape::float_type, {1, 6, 4}}; @@ -5478,8 +5478,8 @@ TEST_CASE(nms_dyn_classes_test) p.compile(migraphx::make_target("ref")); std::vector boxes_vec = {0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, - 0.0, -0.1, 1.0, 0.9, 0.0, 10.0, 1.0, 11.0, - 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}; + 0.0, -0.1, 1.0, 0.9, 0.0, 10.0, 1.0, 11.0, + 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}; std::vector scores_vec = { 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}; migraphx::shape input_fixed_shape0{migraphx::shape::float_type, {1, 6, 4}}; @@ -6564,15 +6564,15 @@ TEST_CASE(reduce_max_axis02) EXPECT(results_vector == gold); } -template -void reduce_op_axes_input_test(const std::string& op_name, +template +void reduce_op_axes_input_test(const std::string op_name, std::vector axes, std::vector gold) { migraphx::program p; auto* mm = p.get_main_module(); auto data_static_shape = migraphx::shape{migraphx::shape::get_type{}, {3, 2, 2}}; - auto data_shape = Dynamic ? migraphx::shape{migraphx::shape::get_type{}, + auto data_shape = dynamic ? migraphx::shape{migraphx::shape::get_type{}, {{2, 5, {}}, {2, 3, {}}, {2, 3, {}}}} : data_static_shape; auto data_param = mm->add_parameter("data", data_shape); From 4b200ca4512fb15a44a3b80ae3a8359cfb0bc8f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Sun, 24 Sep 2023 09:20:35 +0000 Subject: [PATCH 08/25] Restore noop_with_empty_axes attribute --- src/include/migraphx/op/reduce_op.hpp | 20 +++++++++++++------- src/onnx/parse_reduce_op.cpp | 18 ++++++++---------- src/targets/cpu/reduction.cpp | 5 ++++- test/op_shape_test.cpp | 23 ++++++++++++++++------- test/ref_ops_test.cpp | 8 ++++---- 5 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index df6dacf3e5f..ca41da6c0e6 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -80,11 +80,12 @@ template struct reduce_op : op_name { std::vector axes{}; + bool noop_with_empty_axes = false; template static auto reflect(Self& self, F f) { - return pack(f(self.axes, "axes")); + return pack(f(self.axes, "axes"), f(self.noop_with_empty_axes, "noop_with_empty_axes")); } value attributes() const @@ -109,7 +110,7 @@ struct reduce_op : op_name shape compute_dynamic_shape(const std::vector& inputs) const { const auto& data_shape = inputs[0]; - auto dims = data_shape.dyn_dims(); + auto dims = data_shape.dyn_dims(); if(axes.empty()) { for(auto& dim : dims) @@ -125,7 +126,7 @@ struct reduce_op : op_name } } - return shape{data_shape.type(), dims}; + return {data_shape.type(), dims}; } shape compute_static_shape(const std::vector& inputs) const @@ -139,7 +140,7 @@ struct reduce_op : op_name return shape::dynamic_dimension{1, l}; }); - return shape{data_shape.type(), std::move(dims)}; + return {data_shape.type(), std::move(dims)}; } else { @@ -224,7 +225,7 @@ struct reduce_op : op_name argument compute(const dyn_output& dyn_out, std::vector args) const { auto&& data_arg = args[0]; - if(!axes.empty()) + if(not axes.empty()) { return compute(dyn_out.computed_shape, axes, data_arg); } @@ -237,8 +238,13 @@ struct reduce_op : op_name if(reduce_axes.empty()) { - // If axes is empty always treat is a noop - return data_arg; + if(noop_with_empty_axes) + { + return data_arg; + } + + reduce_axes.resize(data_arg.get_shape().ndim()); + std::iota(reduce_axes.begin(), reduce_axes.end(), 0); } const auto result_shape = collapse_reduced_axes(data_arg.get_shape(), reduce_axes); diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index 30ada21c7c2..5b9534850d1 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -36,7 +36,7 @@ static std::optional parse_attribute(const std::string& attribute_name, const onnx_parser& parser, onnx_parser::node_info& info) { - if(!contains(info.attributes, attribute_name)) + if(not contains(info.attributes, attribute_name)) { return std::nullopt; } @@ -60,10 +60,7 @@ instruction_ref parse_reduce_oper(const std::string& op_name, // The reference implementation supports variable axes, but the backends do not MIGRAPHX_THROW("Cannot handle variable axes"); } - else - { - args[1]->eval().visit([&](auto s) { axes.assign(s.begin(), s.end()); }); - } + args[1]->eval().visit([&](auto s) { axes.assign(s.begin(), s.end()); }); } else if(contains(info.attributes, "axes")) { @@ -73,10 +70,10 @@ instruction_ref parse_reduce_oper(const std::string& op_name, int noop_with_empty_axes = parse_attribute("noop_with_empty_axes", parser, info).value_or(0); - // empty axes behavior + if(axes.empty() and not runtime_axes) { - if(noop_with_empty_axes) + if(noop_with_empty_axes != 0) { return args[0]; } @@ -87,14 +84,15 @@ instruction_ref parse_reduce_oper(const std::string& op_name, int keep_dims = parse_attribute("keepdims", parser, info).value_or(1); - auto reduce_op = make_op(op_name, {{"axes", axes}}); + auto reduce_op = + make_op(op_name, {{"axes", axes}, {"noop_with_empty_axes", noop_with_empty_axes}}); auto return_instruction = runtime_axes ? info.add_instruction(reduce_op, args) : info.add_instruction(reduce_op, args[0]); - if(not keep_dims) + if(keep_dims == 0) { if(runtime_axes) { - MIGRAPHX_THROW("Keepdims currently not supported with runtime provided axes"); + MIGRAPHX_THROW("Keepdims not supported with runtime provided axes"); } return_instruction = info.add_instruction(make_op("squeeze", {{"axes", axes}}), return_instruction); diff --git a/src/targets/cpu/reduction.cpp b/src/targets/cpu/reduction.cpp index e0a7517eec9..d8cd872a231 100644 --- a/src/targets/cpu/reduction.cpp +++ b/src/targets/cpu/reduction.cpp @@ -32,11 +32,14 @@ struct dnnl_reduction : dnnl_op { std::string algo; std::vector axes{}; + bool noop_with_empty_axes = true; template static auto reflect(Self& self, F f) { return pack_join(self.reflect_base(self, f), - pack(f(self.algo, "algo"), f(self.axes, "axes"))); + pack(f(self.algo, "algo"), + f(self.axes, "axes"), + f(self.noop_with_empty_axes, "noop_with_empty_axes"))); } std::string name() const { return "dnnl::reduction"; } diff --git a/test/op_shape_test.cpp b/test/op_shape_test.cpp index 22970787851..cdee089a287 100644 --- a/test/op_shape_test.cpp +++ b/test/op_shape_test.cpp @@ -2116,13 +2116,6 @@ TEST_CASE(pooling_shape3) input); } -TEST_CASE(pooling_shape4) -{ - migraphx::shape tiny_input{migraphx::shape::float_type, {4, 1}}; - throws_shape(migraphx::make_op("pooling", {{"mode", migraphx::op::pooling_mode::max}}), - tiny_input); -} - TEST_CASE(pooling_dyn_shape0) { migraphx::shape input{migraphx::shape::float_type, {{1, 4}, {3, 3, {3}}, {3, 3, {3}}, {3, 3}}}; @@ -2347,6 +2340,13 @@ TEST_CASE(dqlinear_mismatch_type) void test_reduce_ops(const std::string& name) { + { + migraphx::shape input{migraphx::shape::float_type, {2, 3, 4, 5}}; + expect_shape(migraphx::shape{migraphx::shape::float_type, {1, 1, 1, 1}}, + migraphx::make_op(name), + input); + } + { migraphx::shape input{migraphx::shape::float_type, {2, 3, 4, 5}}; expect_shape(migraphx::shape{migraphx::shape::float_type, {1, 1, 1, 1}}, @@ -2396,6 +2396,15 @@ void test_dyn_reduce_ops(const std::string& name) migraphx::make_op(name, {{"axes", {0}}}), input); } + { + // Empty axis argument reduces all axes + migraphx::shape input{migraphx::shape::float_type, {{2, 3, {3}}, {2, 4, {4}}}}; + expect_shape( + migraphx::shape{migraphx::shape::float_type, + std::vector({{1, 1}, {1, 1}})}, + migraphx::make_op(name), + input); + } { migraphx::shape input{migraphx::shape::float_type, {{2, 3, {3}}, {2, 4, {4}}}}; throws_shape(migraphx::make_op(name, {{"axes", {4}}}), input); diff --git a/test/ref_ops_test.cpp b/test/ref_ops_test.cpp index f93945c5807..d0cd9777196 100644 --- a/test/ref_ops_test.cpp +++ b/test/ref_ops_test.cpp @@ -6634,16 +6634,16 @@ TEST_CASE(reduce_max_axis02) EXPECT(results_vector == gold); } -template -void reduce_op_axes_input_test(const std::string op_name, +template +void reduce_op_axes_input_test(const std::string& op_name, std::vector axes, std::vector gold) { migraphx::program p; auto* mm = p.get_main_module(); auto data_static_shape = migraphx::shape{migraphx::shape::get_type{}, {3, 2, 2}}; - auto data_shape = dynamic ? migraphx::shape{migraphx::shape::get_type{}, - {{2, 5, {}}, {2, 3, {}}, {2, 3, {}}}} + auto data_shape = Dynamic ? migraphx::shape{migraphx::shape::get_type{}, + {{2, 5, {}}, {2, 3, {}}, {2, 3, {}}}} : data_static_shape; auto data_param = mm->add_parameter("data", data_shape); auto axes_shape = migraphx::shape{migraphx::shape::int64_type, {axes.size()}}; From 075f66330f0f8fb9bc48c6dcfb3945355df95257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Tue, 26 Sep 2023 08:15:17 +0000 Subject: [PATCH 09/25] Add op shape tests for variable axes case --- test/op_shape_test.cpp | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/test/op_shape_test.cpp b/test/op_shape_test.cpp index 61355bc40a8..a82f4bf18df 100644 --- a/test/op_shape_test.cpp +++ b/test/op_shape_test.cpp @@ -2425,13 +2425,6 @@ TEST_CASE(dqlinear_mismatch_type) void test_reduce_ops(const std::string& name) { - { - migraphx::shape input{migraphx::shape::float_type, {2, 3, 4, 5}}; - expect_shape(migraphx::shape{migraphx::shape::float_type, {1, 1, 1, 1}}, - migraphx::make_op(name), - input); - } - { migraphx::shape input{migraphx::shape::float_type, {2, 3, 4, 5}}; expect_shape(migraphx::shape{migraphx::shape::float_type, {1, 1, 1, 1}}, @@ -2482,12 +2475,11 @@ void test_dyn_reduce_ops(const std::string& name) input); } { - // Empty axis argument reduces all axes migraphx::shape input{migraphx::shape::float_type, {{2, 3, {3}}, {2, 4, {4}}}}; expect_shape( migraphx::shape{migraphx::shape::float_type, std::vector({{1, 1}, {1, 1}})}, - migraphx::make_op(name), + migraphx::make_op(name, {{"axes", {0, 1}}}), input); } { @@ -2496,16 +2488,41 @@ void test_dyn_reduce_ops(const std::string& name) } } +void test_reduce_ops_variable_axes(const std::string& name) +{ + { + migraphx::shape input_shape{migraphx::shape::float_type, {2, 3, 4}}; + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + migraphx::shape expected_shape{migraphx::shape::float_type, {{1, 2}, {1, 3}, {1, 4}}}; + expect_shape(expected_shape, migraphx::make_op(name), input_shape, axes_shape); + } + + { + migraphx::shape input_shape{migraphx::shape::float_type, {{2, 3}, {3, 4}}}; + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + migraphx::shape expected_shape{migraphx::shape::float_type, {{1, 3}, {1, 4}}}; + expect_shape(expected_shape, migraphx::make_op(name), input_shape, axes_shape); + } +} + TEST_CASE(reduce_max) { test_reduce_ops("reduce_max"); } +TEST_CASE(reduce_min) { test_reduce_ops("reduce_min"); } TEST_CASE(reduce_mean) { test_reduce_ops("reduce_mean"); } TEST_CASE(reduce_prod) { test_reduce_ops("reduce_prod"); } TEST_CASE(reduce_sum) { test_reduce_ops("reduce_sum"); } TEST_CASE(reduce_max_dyn) { test_dyn_reduce_ops("reduce_max"); } +TEST_CASE(reduce_min_dyn) { test_dyn_reduce_ops("reduce_min"); } TEST_CASE(reduce_mean_dyn) { test_dyn_reduce_ops("reduce_mean"); } TEST_CASE(reduce_prod_dyn) { test_dyn_reduce_ops("reduce_prod"); } TEST_CASE(reduce_sum_dyn) { test_dyn_reduce_ops("reduce_sum"); } +TEST_CASE(reduce_max_variable_axes) { test_reduce_ops_variable_axes("reduce_max"); } +TEST_CASE(reduce_min_variable_axes) { test_reduce_ops_variable_axes("reduce_min"); } +TEST_CASE(reduce_mean_variable_axes) { test_reduce_ops_variable_axes("reduce_mean"); } +TEST_CASE(reduce_prod_variable_axes) { test_reduce_ops_variable_axes("reduce_prod"); } +TEST_CASE(reduce_sum_variable_axes) { test_reduce_ops_variable_axes("reduce_sum"); } + TEST_CASE(reshape_shape) { migraphx::shape input{migraphx::shape::float_type, {24, 1, 1, 1}}; From 2919f1db7446a59044777ef8846216ac89bba872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Tue, 26 Sep 2023 09:21:34 +0000 Subject: [PATCH 10/25] Implement onnx parsing tests for variable axes --- src/onnx/parse_reduce_op.cpp | 16 ++--- test/onnx/gen_onnx.py | 63 +++++++++++++++++++ test/onnx/onnx_test.cpp | 50 +++++++++++++++ ...reduce_log_sum_exp_variable_axes_test.onnx | 21 +++++++ .../reduce_log_sum_variable_axes_test.onnx | 21 +++++++ test/onnx/reducel1_variable_axes_test.onnx | 21 +++++++ test/onnx/reducel2_variable_axes_test.onnx | 21 +++++++ test/onnx/reducemax_variable_axes_test.onnx | 21 +++++++ test/onnx/reducemean_variable_axes_test.onnx | 22 +++++++ test/onnx/reducemin_variable_axes_test.onnx | 21 +++++++ test/onnx/reduceprod_variable_axes_test.onnx | 22 +++++++ .../reducesum_square_variable_axes_test.onnx | 21 +++++++ test/onnx/reducesum_variable_axes_test.onnx | 21 +++++++ 13 files changed, 333 insertions(+), 8 deletions(-) create mode 100644 test/onnx/reduce_log_sum_exp_variable_axes_test.onnx create mode 100644 test/onnx/reduce_log_sum_variable_axes_test.onnx create mode 100644 test/onnx/reducel1_variable_axes_test.onnx create mode 100644 test/onnx/reducel2_variable_axes_test.onnx create mode 100644 test/onnx/reducemax_variable_axes_test.onnx create mode 100644 test/onnx/reducemean_variable_axes_test.onnx create mode 100644 test/onnx/reducemin_variable_axes_test.onnx create mode 100644 test/onnx/reduceprod_variable_axes_test.onnx create mode 100644 test/onnx/reducesum_square_variable_axes_test.onnx create mode 100644 test/onnx/reducesum_variable_axes_test.onnx diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index 5b9534850d1..4f26cd7737d 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -130,8 +130,8 @@ struct parse_reduce_l1 : op_parser onnx_parser::node_info info, std::vector args) const { - auto abs_ins = info.add_instruction(make_op("abs"), args[0]); - return parse_reduce_oper("reduce_sum", parser, std::move(info), {abs_ins}); + args[0] = info.add_instruction(make_op("abs"), args[0]); + return parse_reduce_oper("reduce_sum", parser, std::move(info), std::move(args)); } }; @@ -144,8 +144,8 @@ struct parse_reduce_l2 : op_parser const onnx_parser::node_info& info, std::vector args) const { - auto square_ins = info.add_instruction(make_op("mul"), args[0], args[0]); - auto sum_ins = parse_reduce_oper("reduce_sum", parser, info, {square_ins}); + args[0] = info.add_instruction(make_op("mul"), args[0], args[0]); + auto sum_ins = parse_reduce_oper("reduce_sum", parser, info, std::move(args)); return info.add_instruction(make_op("sqrt"), sum_ins); } }; @@ -173,8 +173,8 @@ struct parse_reduce_log_sum_exp : op_parser const onnx_parser::node_info& info, std::vector args) const { - auto exp_ins = info.add_instruction(make_op("exp"), args[0]); - auto sum_ins = parse_reduce_oper("reduce_sum", parser, info, {exp_ins}); + args[0] = info.add_instruction(make_op("exp"), args[0]); + auto sum_ins = parse_reduce_oper("reduce_sum", parser, info, std::move(args)); return info.add_instruction(make_op("log"), sum_ins); } }; @@ -188,8 +188,8 @@ struct parse_reduce_sum_square : op_parser onnx_parser::node_info info, std::vector args) const { - auto square_ins = info.add_instruction(make_op("mul"), args[0], args[0]); - return parse_reduce_oper("reduce_sum", parser, std::move(info), {square_ins}); + args[0] = info.add_instruction(make_op("mul"), args[0], args[0]); + return parse_reduce_oper("reduce_sum", parser, std::move(info), std::move(args)); } }; diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index b1cc1cd96cc..fd0fc153afd 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -5398,6 +5398,19 @@ def recip_test(): return ([node], [x], [y]) +def reduceop_variable_axes_test(op_name): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) + axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [1]); + y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 1, 6]) + + node = onnx.helper.make_node(op_name, + inputs=['x', 'axes'], + outputs=['y'], + keepdims=1) + + return ([node], [x, axes], [y]) + + @onnx_test() def reducel1_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5441,6 +5454,11 @@ def reducel1_dyn_noaxes_test(): return ([node], [x], [y]) +@onnx_test() +def reducel1_variable_axes_test(): + return reduceop_variable_axes_test('ReduceL1') + + @onnx_test() def reducel2_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5456,6 +5474,11 @@ def reducel2_test(): return ([node], [x], [y]) +@onnx_test() +def reducel2_variable_axes_test(): + return reduceop_variable_axes_test('ReduceL2') + + @onnx_test() def reduce_log_sum_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5471,6 +5494,11 @@ def reduce_log_sum_test(): return ([node], [x], [y]) +@onnx_test() +def reduce_log_sum_variable_axes_test(): + return reduceop_variable_axes_test('ReduceLogSum') + + @onnx_test() def reduce_log_sum_exp_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5486,6 +5514,11 @@ def reduce_log_sum_exp_test(): return ([node], [x], [y]) +@onnx_test() +def reduce_log_sum_exp_variable_axes_test(): + return reduceop_variable_axes_test('ReduceLogSumExp') + + @onnx_test() def reducemax_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5517,6 +5550,11 @@ def reducemax_dyn_test(): return ([node], [x], [y]) +@onnx_test() +def reducemax_variable_axes_test(): + return reduceop_variable_axes_test('ReduceMax') + + @onnx_test() def reducemean_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5547,6 +5585,11 @@ def reducemean_keepdims_test(): return ([node], [x], [y]) +@onnx_test() +def reducemean_variable_axes_test(): + return reduceop_variable_axes_test('ReduceMean') + + @onnx_test() def reducemin_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5562,6 +5605,11 @@ def reducemin_test(): return ([node], [x], [y]) +@onnx_test() +def reducemin_variable_axes_test(): + return reduceop_variable_axes_test('ReduceMin') + + @onnx_test() def reduceprod_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5577,6 +5625,11 @@ def reduceprod_test(): return ([node], [x], [y]) +@onnx_test() +def reduceprod_variable_axes_test(): + return reduceop_variable_axes_test('ReduceProd') + + @onnx_test() def reducesum_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5660,6 +5713,11 @@ def reducesum_multiaxis_test(): return ([node], [x], [y]) +@onnx_test() +def reducesum_variable_axes_test(): + return reduceop_variable_axes_test('ReduceSum') + + @onnx_test() def reducesum_square_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -5675,6 +5733,11 @@ def reducesum_square_test(): return ([node], [x], [y]) +@onnx_test() +def reducesum_square_variable_axes_test(): + return reduceop_variable_axes_test('ReduceSumSquare') + + @onnx_test() def reshape_test(): x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [4, 2, 3]) diff --git a/test/onnx/onnx_test.cpp b/test/onnx/onnx_test.cpp index b0e6255a976..bba41e5d6c3 100644 --- a/test/onnx/onnx_test.cpp +++ b/test/onnx/onnx_test.cpp @@ -5167,6 +5167,11 @@ TEST_CASE(reducel1_dyn_test) } } +TEST_CASE(reducel1_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reducel1_variable_axes_test.onnx"); })); +} + TEST_CASE(reducel2_test) { migraphx::program p; @@ -5181,6 +5186,11 @@ TEST_CASE(reducel2_test) EXPECT(p == prog); } +TEST_CASE(reducel2_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reducel2_variable_axes_test.onnx"); })); +} + TEST_CASE(reduce_log_sum_test) { migraphx::program p; @@ -5193,6 +5203,11 @@ TEST_CASE(reduce_log_sum_test) EXPECT(p == prog); } +TEST_CASE(reduce_log_sum_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reduce_log_sum_variable_axes_test.onnx"); })); +} + TEST_CASE(reduce_log_sum_exp_test) { migraphx::program p; @@ -5206,6 +5221,11 @@ TEST_CASE(reduce_log_sum_exp_test) EXPECT(p == prog); } +TEST_CASE(reduce_log_sum_exp_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reduce_log_sum_exp_variable_axes_test.onnx"); })); +} + TEST_CASE(reducemax_test) { migraphx::program p; @@ -5235,6 +5255,11 @@ TEST_CASE(reducemax_dyn_test) EXPECT(p == prog); } +TEST_CASE(reducemax_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reducemax_variable_axes_test.onnx"); })); +} + TEST_CASE(reducemean_test) { migraphx::program p; @@ -5258,6 +5283,11 @@ TEST_CASE(reducemean_keepdims_test) EXPECT(p == prog); } +TEST_CASE(reducemean_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reducemean_variable_axes_test.onnx"); })); +} + TEST_CASE(reducemin_test) { migraphx::program p; @@ -5270,6 +5300,11 @@ TEST_CASE(reducemin_test) EXPECT(p == prog); } +TEST_CASE(reducemin_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reducemin_variable_axes_test.onnx"); })); +} + TEST_CASE(reduceprod_test) { migraphx::program p; @@ -5281,6 +5316,11 @@ TEST_CASE(reduceprod_test) EXPECT(p == prog); } +TEST_CASE(reduceprod_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reduceprod_variable_axes_test.onnx"); })); +} + TEST_CASE(reducesum_test) { migraphx::program p; @@ -5343,6 +5383,11 @@ TEST_CASE(reducesum_keepdims_test) EXPECT(p == prog); } +TEST_CASE(reducesum_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reducesum_variable_axes_test.onnx"); })); +} + TEST_CASE(reducesum_square_test) { migraphx::program p; @@ -5356,6 +5401,11 @@ TEST_CASE(reducesum_square_test) EXPECT(p == prog); } +TEST_CASE(reducesum_square_variable_axes_test) +{ + EXPECT(test::throws([&] { migraphx::parse_onnx("reducesum_square_variable_axes_test.onnx"); })); +} + TEST_CASE(reshape_test) { migraphx::program p; diff --git a/test/onnx/reduce_log_sum_exp_variable_axes_test.onnx b/test/onnx/reduce_log_sum_exp_variable_axes_test.onnx new file mode 100644 index 00000000000..fac02d3bfba --- /dev/null +++ b/test/onnx/reduce_log_sum_exp_variable_axes_test.onnx @@ -0,0 +1,21 @@ + %reduce_log_sum_exp_variable_axes_test:₯ +. +x +axesy"ReduceLogSumExp* +keepdims %reduce_log_sum_exp_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reduce_log_sum_variable_axes_test.onnx b/test/onnx/reduce_log_sum_variable_axes_test.onnx new file mode 100644 index 00000000000..88587aefef6 --- /dev/null +++ b/test/onnx/reduce_log_sum_variable_axes_test.onnx @@ -0,0 +1,21 @@ + !reduce_log_sum_variable_axes_test:ž ++ +x +axesy" ReduceLogSum* +keepdims !reduce_log_sum_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducel1_variable_axes_test.onnx b/test/onnx/reducel1_variable_axes_test.onnx new file mode 100644 index 00000000000..e2674307bca --- /dev/null +++ b/test/onnx/reducel1_variable_axes_test.onnx @@ -0,0 +1,21 @@ + reducel1_variable_axes_test:” +' +x +axesy"ReduceL1* +keepdims reducel1_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducel2_variable_axes_test.onnx b/test/onnx/reducel2_variable_axes_test.onnx new file mode 100644 index 00000000000..b4e81db6d11 --- /dev/null +++ b/test/onnx/reducel2_variable_axes_test.onnx @@ -0,0 +1,21 @@ + reducel2_variable_axes_test:” +' +x +axesy"ReduceL2* +keepdims reducel2_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducemax_variable_axes_test.onnx b/test/onnx/reducemax_variable_axes_test.onnx new file mode 100644 index 00000000000..030160ca1ca --- /dev/null +++ b/test/onnx/reducemax_variable_axes_test.onnx @@ -0,0 +1,21 @@ + reducemax_variable_axes_test:– +( +x +axesy" ReduceMax* +keepdims reducemax_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducemean_variable_axes_test.onnx b/test/onnx/reducemean_variable_axes_test.onnx new file mode 100644 index 00000000000..77002df2d13 --- /dev/null +++ b/test/onnx/reducemean_variable_axes_test.onnx @@ -0,0 +1,22 @@ + reducemean_variable_axes_test:˜ +) +x +axesy" +ReduceMean* +keepdims reducemean_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducemin_variable_axes_test.onnx b/test/onnx/reducemin_variable_axes_test.onnx new file mode 100644 index 00000000000..58aa4f094e2 --- /dev/null +++ b/test/onnx/reducemin_variable_axes_test.onnx @@ -0,0 +1,21 @@ + reducemin_variable_axes_test:– +( +x +axesy" ReduceMin* +keepdims reducemin_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reduceprod_variable_axes_test.onnx b/test/onnx/reduceprod_variable_axes_test.onnx new file mode 100644 index 00000000000..f7fc5ef97a6 --- /dev/null +++ b/test/onnx/reduceprod_variable_axes_test.onnx @@ -0,0 +1,22 @@ + reduceprod_variable_axes_test:˜ +) +x +axesy" +ReduceProd* +keepdims reduceprod_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducesum_square_variable_axes_test.onnx b/test/onnx/reducesum_square_variable_axes_test.onnx new file mode 100644 index 00000000000..4b2a93bbab0 --- /dev/null +++ b/test/onnx/reducesum_square_variable_axes_test.onnx @@ -0,0 +1,21 @@ + #reducesum_square_variable_axes_test:£ +. +x +axesy"ReduceSumSquare* +keepdims #reducesum_square_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducesum_variable_axes_test.onnx b/test/onnx/reducesum_variable_axes_test.onnx new file mode 100644 index 00000000000..00cffbd9cfd --- /dev/null +++ b/test/onnx/reducesum_variable_axes_test.onnx @@ -0,0 +1,21 @@ + reducesum_variable_axes_test:– +( +x +axesy" ReduceSum* +keepdims reducesum_variable_axes_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file From 2fbd708dda33f632b175bc39b7df1072b7caf5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Tue, 26 Sep 2023 14:42:31 +0000 Subject: [PATCH 11/25] Add reference operator tests --- test/onnx/gen_onnx.py | 2 +- test/onnx/onnx_test.cpp | 3 +- test/ref/reduce_max.cpp | 100 ++++++++++++++++++++++++++ test/ref/reduce_mean.cpp | 125 ++++++++++++++++++++++++++++++++ test/ref/reduce_min.cpp | 100 ++++++++++++++++++++++++++ test/ref/reduce_prod.cpp | 25 +++++++ test/ref/reduce_sum.cpp | 150 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 503 insertions(+), 2 deletions(-) diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index fd0fc153afd..2c17255b357 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -5400,7 +5400,7 @@ def recip_test(): def reduceop_variable_axes_test(op_name): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) - axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [1]); + axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [1]) y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 1, 6]) node = onnx.helper.make_node(op_name, diff --git a/test/onnx/onnx_test.cpp b/test/onnx/onnx_test.cpp index bba41e5d6c3..c03d14baea2 100644 --- a/test/onnx/onnx_test.cpp +++ b/test/onnx/onnx_test.cpp @@ -5223,7 +5223,8 @@ TEST_CASE(reduce_log_sum_exp_test) TEST_CASE(reduce_log_sum_exp_variable_axes_test) { - EXPECT(test::throws([&] { migraphx::parse_onnx("reduce_log_sum_exp_variable_axes_test.onnx"); })); + EXPECT( + test::throws([&] { migraphx::parse_onnx("reduce_log_sum_exp_variable_axes_test.onnx"); })); } TEST_CASE(reducemax_test) diff --git a/test/ref/reduce_max.cpp b/test/ref/reduce_max.cpp index 19b4cc9ec62..aa55e96fe0a 100644 --- a/test/ref/reduce_max.cpp +++ b/test/ref/reduce_max.cpp @@ -46,6 +46,31 @@ TEST_CASE(reduce_max_axis0) EXPECT(results_vector == gold); } +TEST_CASE(reduce_max_variable_axis0) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_max"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{0}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{9, 10, 11, 12}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_max_dynamic_axis0) { migraphx::program p; @@ -67,6 +92,31 @@ TEST_CASE(reduce_max_dynamic_axis0) EXPECT(migraphx::verify::verify_range(results_vector, gold)); } +TEST_CASE(reduce_max_dynamic_variable_axis0) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + migraphx::shape x_shape{migraphx::shape::float_type, {{2, 4, {2}}, {3, 5, {3}}}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_max"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + migraphx::shape x_fixed_shape{migraphx::shape::float_type, {2, 5}}; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + pm["x"] = migraphx::argument(x_fixed_shape, x_arg.data()); + std::vector axes_arg{0}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold = {6, 7, 8, 9, 10}; + EXPECT(migraphx::verify::verify_range(results_vector, gold)); +} + TEST_CASE(reduce_max_axis01) { migraphx::program p; @@ -83,6 +133,31 @@ TEST_CASE(reduce_max_axis01) EXPECT(results_vector == gold); } +TEST_CASE(reduce_max_variable_axes01) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_max"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{0, 1}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{11, 12}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_max_axis02) { migraphx::program p; @@ -98,3 +173,28 @@ TEST_CASE(reduce_max_axis02) std::vector gold{10, 12}; EXPECT(results_vector == gold); } + +TEST_CASE(reduce_max_variable_axes02) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_max"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{0, 2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{10, 12}; + EXPECT(results_vector == gold); +} diff --git a/test/ref/reduce_mean.cpp b/test/ref/reduce_mean.cpp index fb7c2b421c3..ff6fa7d3190 100644 --- a/test/ref/reduce_mean.cpp +++ b/test/ref/reduce_mean.cpp @@ -46,6 +46,31 @@ TEST_CASE(reduce_mean_axis02) EXPECT(results_vector == gold); } +TEST_CASE(reduce_mean_variable_axes02) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_mean"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{0, 2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{5.5, 7.5}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_mean_axis1) { migraphx::program p; @@ -62,6 +87,31 @@ TEST_CASE(reduce_mean_axis1) EXPECT(results_vector == gold); } +TEST_CASE(reduce_mean_variable_axis1) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_mean"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{1}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{2, 3, 6, 7, 10, 11}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_mean_axis12) { migraphx::program p; @@ -78,6 +128,31 @@ TEST_CASE(reduce_mean_axis12) EXPECT(results_vector == gold); } +TEST_CASE(reduce_mean_variable_axes12) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_mean"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{1, 2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{2.5, 6.5, 10.5}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_mean_axis2) { migraphx::program p; @@ -94,6 +169,31 @@ TEST_CASE(reduce_mean_axis2) EXPECT(results_vector == gold); } +TEST_CASE(reduce_mean_variable_axis2) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_mean"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{1.5f, 3.5f, 5.5f, 7.5f, 9.5f, 11.5f}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_mean_int) { migraphx::program p; @@ -109,3 +209,28 @@ TEST_CASE(reduce_mean_int) std::vector gold{2, 6, 10}; EXPECT(results_vector == gold); } + +TEST_CASE(reduce_mean_variable_axes12_int) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::int32_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_mean"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{1, 2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{2, 6, 10}; + EXPECT(results_vector == gold); +} diff --git a/test/ref/reduce_min.cpp b/test/ref/reduce_min.cpp index e1f1796bf03..ddb34edc5ea 100644 --- a/test/ref/reduce_min.cpp +++ b/test/ref/reduce_min.cpp @@ -46,6 +46,31 @@ TEST_CASE(reduce_min_axis02) EXPECT(results_vector == gold); } +TEST_CASE(reduce_min_variable_axes02) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_min"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{0, 2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{1, 3}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_min_axis1) { migraphx::program p; @@ -62,6 +87,31 @@ TEST_CASE(reduce_min_axis1) EXPECT(results_vector == gold); } +TEST_CASE(reduce_min_variable_axis1) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_min"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{1}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{1, 2, 5, 6, 9, 10}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_min_axis12) { migraphx::program p; @@ -77,3 +127,53 @@ TEST_CASE(reduce_min_axis12) std::vector gold{1, 5, 9}; EXPECT(results_vector == gold); } + +TEST_CASE(reduce_min_variable_axes12) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_min"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{1, 2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{1, 5, 9}; + EXPECT(results_vector == gold); +} + +TEST_CASE(reduce_min_dynamic_variable_axis0) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + migraphx::shape x_shape{migraphx::shape::float_type, {{2, 4, {2}}, {3, 5, {3}}}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_min"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + migraphx::shape x_fixed_shape{migraphx::shape::float_type, {2, 5}}; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + pm["x"] = migraphx::argument(x_fixed_shape, x_arg.data()); + std::vector axes_arg{0}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold = {1, 2, 3, 4, 5}; + EXPECT(migraphx::verify::verify_range(results_vector, gold)); +} diff --git a/test/ref/reduce_prod.cpp b/test/ref/reduce_prod.cpp index 9c2a9b180b5..909bb931a2f 100644 --- a/test/ref/reduce_prod.cpp +++ b/test/ref/reduce_prod.cpp @@ -45,3 +45,28 @@ TEST_CASE(reduce_prod_axis0) std::vector gold{6, 18, 12, 18}; EXPECT(results_vector == gold); } + +TEST_CASE(reduce_prod_variable_axis0) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {4, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_prod"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 3, 2, 3}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{0}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{6, 18, 12, 18}; + EXPECT(results_vector == gold); +} diff --git a/test/ref/reduce_sum.cpp b/test/ref/reduce_sum.cpp index 51514a719c2..9b33c8e0a62 100644 --- a/test/ref/reduce_sum.cpp +++ b/test/ref/reduce_sum.cpp @@ -46,6 +46,31 @@ TEST_CASE(reduce_sum_axis0) EXPECT(results_vector == gold); } +TEST_CASE(reduce_sum_variable_axis0) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_sum"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{0}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{15, 18, 21, 24}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_sum_axis02) { migraphx::program p; @@ -62,6 +87,31 @@ TEST_CASE(reduce_sum_axis02) EXPECT(results_vector == gold); } +TEST_CASE(reduce_sum_variable_axes02) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_sum"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{0, 2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{33, 45}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_sum_axis1) { migraphx::program p; @@ -78,6 +128,31 @@ TEST_CASE(reduce_sum_axis1) EXPECT(results_vector == gold); } +TEST_CASE(reduce_sum_variable_axis1) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_sum"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{1}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{4, 6, 12, 14, 20, 22}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_sum_axis12) { migraphx::program p; @@ -94,6 +169,31 @@ TEST_CASE(reduce_sum_axis12) EXPECT(results_vector == gold); } +TEST_CASE(reduce_sum_variable_axes12) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {2}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_sum"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{1, 2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{10, 26, 42}; + EXPECT(results_vector == gold); +} + TEST_CASE(reduce_sum_axis2) { migraphx::program p; @@ -109,3 +209,53 @@ TEST_CASE(reduce_sum_axis2) std::vector gold{3, 7, 11, 15, 19, 23}; EXPECT(results_vector == gold); } + +TEST_CASE(reduce_sum_variable_axis2) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + + migraphx::shape x_shape{migraphx::shape::float_type, {3, 2, 2}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_sum"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + pm["x"] = migraphx::argument(x_shape, x_arg.data()); + std::vector axes_arg{2}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold{3, 7, 11, 15, 19, 23}; + EXPECT(results_vector == gold); +} + +TEST_CASE(reduce_sum_dynamic_variable_axis0) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + migraphx::shape x_shape{migraphx::shape::float_type, {{2, 4, {2}}, {3, 5, {3}}}}; + auto x = mm->add_parameter("x", x_shape); + migraphx::shape axes_shape{migraphx::shape::int64_type, {1}}; + auto axes = mm->add_parameter("axes", axes_shape); + mm->add_instruction(migraphx::make_op("reduce_sum"), x, axes); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + migraphx::shape x_fixed_shape{migraphx::shape::float_type, {2, 5}}; + std::vector x_arg{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + pm["x"] = migraphx::argument(x_fixed_shape, x_arg.data()); + std::vector axes_arg{0}; + pm["axes"] = migraphx::argument(axes_shape, axes_arg.data()); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + std::vector gold = {7, 9, 11, 13, 15}; + EXPECT(migraphx::verify::verify_range(results_vector, gold)); +} From af061751303a49dc4c518a82a1c6185dda88caeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Mon, 2 Oct 2023 06:21:10 +0000 Subject: [PATCH 12/25] Update verify_range uses to verify_rms_range in reduce op reference tests --- test/ref/reduce_max.cpp | 2 +- test/ref/reduce_min.cpp | 2 +- test/ref/reduce_sum.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/ref/reduce_max.cpp b/test/ref/reduce_max.cpp index 23485e783ac..6f79e2e11b0 100644 --- a/test/ref/reduce_max.cpp +++ b/test/ref/reduce_max.cpp @@ -114,7 +114,7 @@ TEST_CASE(reduce_max_dynamic_variable_axis0) result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); std::vector gold = {6, 7, 8, 9, 10}; - EXPECT(migraphx::verify::verify_range(results_vector, gold)); + EXPECT(migraphx::verify::verify_rms_range(results_vector, gold)); } TEST_CASE(reduce_max_axis01) diff --git a/test/ref/reduce_min.cpp b/test/ref/reduce_min.cpp index ddb34edc5ea..081019acfff 100644 --- a/test/ref/reduce_min.cpp +++ b/test/ref/reduce_min.cpp @@ -175,5 +175,5 @@ TEST_CASE(reduce_min_dynamic_variable_axis0) result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); std::vector gold = {1, 2, 3, 4, 5}; - EXPECT(migraphx::verify::verify_range(results_vector, gold)); + EXPECT(migraphx::verify::verify_rms_range(results_vector, gold)); } diff --git a/test/ref/reduce_sum.cpp b/test/ref/reduce_sum.cpp index 9b33c8e0a62..0f73d28109e 100644 --- a/test/ref/reduce_sum.cpp +++ b/test/ref/reduce_sum.cpp @@ -257,5 +257,5 @@ TEST_CASE(reduce_sum_dynamic_variable_axis0) result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); std::vector gold = {7, 9, 11, 13, 15}; - EXPECT(migraphx::verify::verify_range(results_vector, gold)); + EXPECT(migraphx::verify::verify_rms_range(results_vector, gold)); } From 0cd9b14a21a38cbcf1b48f6e4739d854ebb6ebb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Thu, 25 Jan 2024 15:21:57 +0000 Subject: [PATCH 13/25] Rejig reduce operator parsing to remove complexity from the operator implementation --- src/include/migraphx/op/reduce_op.hpp | 8 +- src/onnx/parse_reduce_op.cpp | 158 ++++++++++++++++---------- src/targets/cpu/reduction.cpp | 5 +- 3 files changed, 103 insertions(+), 68 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 8f36557190e..3de31d1ed44 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -80,12 +80,11 @@ template struct reduce_op : op_name { std::vector axes{}; - bool noop_with_empty_axes = false; template static auto reflect(Self& self, F f) { - return pack(f(self.axes, "axes"), f(self.noop_with_empty_axes, "noop_with_empty_axes")); + return pack(f(self.axes, "axes")); } value attributes() const @@ -238,11 +237,6 @@ struct reduce_op : op_name if(reduce_axes.empty()) { - if(noop_with_empty_axes) - { - return data_arg; - } - reduce_axes.resize(data_arg.get_shape().ndim()); std::iota(reduce_axes.begin(), reduce_axes.end(), 0); } diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index a35bd78d906..9459bc694ec 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,77 +31,121 @@ namespace migraphx { inline namespace MIGRAPHX_INLINE_NS { namespace onnx { -template -static std::optional parse_attribute(const std::string& attribute_name, - const onnx_parser& parser, - onnx_parser::node_info& info) +template +struct reduce_parser : op_parser { - if(not contains(info.attributes, attribute_name)) + instruction_ref parse_reduce_oper(const std::string& op_name, + const onnx_parser& parser, + onnx_parser::node_info info, + std::vector args) const { - return std::nullopt; - } + auto constant_axes = parse_constant_axes(args, info); - return parser.parse_value(info.attributes.at(attribute_name)).at(); -} + int noop_with_empty_axes = + parse_attribute("noop_with_empty_axes", parser, info).value_or(0); -instruction_ref parse_reduce_oper(const std::string& op_name, - const onnx_parser& parser, - onnx_parser::node_info info, - std::vector args) -{ - // default to reduce over all dimensions - std::vector axes; - bool runtime_axes = false; - if(args.size() == 2) - { - runtime_axes = not args[1]->can_eval(); - if(runtime_axes) + int keep_dims = parse_attribute("keepdims", parser, info).value_or(1); + + std::vector all_axes(args.front()->get_shape().ndim()); + std::iota(all_axes.begin(), all_axes.end(), 0); + + if(constant_axes.has_value()) { - // The reference implementation supports variable axes, but the backends do not - MIGRAPHX_THROW("Cannot handle variable axes"); + if(noop_with_empty_axes != 0 and constant_axes->empty()) + { + return args[0]; + } + + if(noop_with_empty_axes == 0 and constant_axes->empty()) + { + constant_axes = all_axes; + } + + auto reduce = + info.add_instruction(make_op(op_name, {{"axes", *constant_axes}}), args[0]); + if(keep_dims == 0) + { + return info.add_instruction(make_op("squeeze", {{"axes", *constant_axes}}), reduce); + } + return reduce; } - args[1]->eval().visit([&](auto s) { axes.assign(s.begin(), s.end()); }); - } - else if(contains(info.attributes, "axes")) - { - auto&& attr_axes = info.attributes["axes"].ints(); - axes.assign(attr_axes.begin(), attr_axes.end()); - } - int noop_with_empty_axes = - parse_attribute("noop_with_empty_axes", parser, info).value_or(0); + if(keep_dims == 0) + { + MIGRAPHX_THROW("Keepdims not supported with runtime provided axes"); + } + // Empty axes attribute indicates to the operator to look for axes in the inputs + auto reduce_op = make_op(op_name, {{"axes", {}}}); - if(axes.empty() and not runtime_axes) - { if(noop_with_empty_axes != 0) { - return args[0]; + return info.add_instruction(reduce_op, args); } - axes.resize(args.front()->get_shape().ndim()); - std::iota(axes.begin(), axes.end(), 0); + if(args[1]->get_shape().dynamic()) + { + auto reduce_input_axes = info.add_instruction(reduce_op, args); + auto all_axes_lit = info.add_literal( + literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); + auto reduce_all_axes = info.add_instruction(reduce_op, args[0], all_axes_lit); + auto zero = info.add_literal(literal{shape{shape::type_t::int64_type}, {0u}}); + auto axes_size = info.add_instruction(make_op("dimensions_of", {{"end", 1}}), args[1]); + auto is_axes_empty = info.add_instruction(make_op("equal"), axes_size, zero); + auto is_axes_empty_bc = + info.add_instruction(make_op("multibroadcast"), is_axes_empty, reduce_all_axes); + + return info.add_instruction( + make_op("where"), is_axes_empty_bc, reduce_all_axes, reduce_input_axes); + } + else if(args[1]->get_shape().elements() == 0) + { + auto all_axes_lit = info.add_literal( + literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); + return info.add_instruction(reduce_op, args[0], all_axes_lit); + } + else + { + return info.add_instruction(reduce_op, args); + } } - int keep_dims = parse_attribute("keepdims", parser, info).value_or(1); - - auto reduce_op = - make_op(op_name, {{"axes", axes}, {"noop_with_empty_axes", noop_with_empty_axes}}); - auto return_instruction = runtime_axes ? info.add_instruction(reduce_op, args) - : info.add_instruction(reduce_op, args[0]); - if(keep_dims == 0) + private: + template + std::optional parse_attribute(const std::string& attribute_name, + const onnx_parser& parser, + onnx_parser::node_info& info) const { - if(runtime_axes) + if(not contains(info.attributes, attribute_name)) { - MIGRAPHX_THROW("Keepdims not supported with runtime provided axes"); + return std::nullopt; } - return_instruction = - info.add_instruction(make_op("squeeze", {{"axes", axes}}), return_instruction); + + return parser.parse_value(info.attributes.at(attribute_name)).at(); } - return return_instruction; -} + std::optional> parse_constant_axes(std::vector& args, + onnx_parser::node_info& info) const + { + std::vector axes; + if(args.size() == 2) + { + if(not args[1]->can_eval()) + { + return std::nullopt; + } + args[1]->eval().visit([&](auto s) { axes.assign(s.begin(), s.end()); }); + } + else if(contains(info.attributes, "axes")) + { + auto&& attr_axes = info.attributes["axes"].ints(); + axes.assign(attr_axes.begin(), attr_axes.end()); + } + + return axes; + } +}; -struct parse_reduce_op : op_parser +struct parse_reduce_op : reduce_parser { std::vector operators() const { @@ -121,7 +165,7 @@ struct parse_reduce_op : op_parser } }; -struct parse_reduce_l1 : op_parser +struct parse_reduce_l1 : reduce_parser { std::vector operators() const { return {{"ReduceL1"}}; } @@ -135,7 +179,7 @@ struct parse_reduce_l1 : op_parser } }; -struct parse_reduce_l2 : op_parser +struct parse_reduce_l2 : reduce_parser { std::vector operators() const { return {{"ReduceL2"}}; } @@ -150,7 +194,7 @@ struct parse_reduce_l2 : op_parser } }; -struct parse_reduce_log_sum : op_parser +struct parse_reduce_log_sum : reduce_parser { std::vector operators() const { return {{"ReduceLogSum"}}; } @@ -164,7 +208,7 @@ struct parse_reduce_log_sum : op_parser } }; -struct parse_reduce_log_sum_exp : op_parser +struct parse_reduce_log_sum_exp : reduce_parser { std::vector operators() const { return {{"ReduceLogSumExp"}}; } @@ -179,7 +223,7 @@ struct parse_reduce_log_sum_exp : op_parser } }; -struct parse_reduce_sum_square : op_parser +struct parse_reduce_sum_square : reduce_parser { std::vector operators() const { return {{"ReduceSumSquare"}}; } diff --git a/src/targets/cpu/reduction.cpp b/src/targets/cpu/reduction.cpp index d8cd872a231..e0a7517eec9 100644 --- a/src/targets/cpu/reduction.cpp +++ b/src/targets/cpu/reduction.cpp @@ -32,14 +32,11 @@ struct dnnl_reduction : dnnl_op { std::string algo; std::vector axes{}; - bool noop_with_empty_axes = true; template static auto reflect(Self& self, F f) { return pack_join(self.reflect_base(self, f), - pack(f(self.algo, "algo"), - f(self.axes, "axes"), - f(self.noop_with_empty_axes, "noop_with_empty_axes"))); + pack(f(self.algo, "algo"), f(self.axes, "axes"))); } std::string name() const { return "dnnl::reduction"; } From 0bcca87a39bbcc53f09920daabd75b5b9d43f84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Mon, 29 Jan 2024 08:16:50 +0000 Subject: [PATCH 14/25] Implement parsing tests for ReduceL1 --- src/include/migraphx/op/reduce_op.hpp | 26 +++----- src/onnx/parse_reduce_op.cpp | 4 +- test/onnx/gen_onnx.py | 60 ++++++++++++++---- test/onnx/parse/reducel1_empty_axes_test.cpp | 37 +++++++++++ .../parse/reducel1_keepdims_clear_test.cpp | 37 +++++++++++ test/onnx/parse/reducel1_noop_test.cpp | 35 ++++++++++ test/onnx/parse/reducel1_test.cpp | 13 ++-- ...cel1_variable_axes_keepdims_clear_test.cpp | 30 +++++++++ .../reducel1_variable_axes_noop_set_test.cpp | 39 ++++++++++++ .../parse/reducel1_variable_axes_test.cpp | 39 ++++++++++++ .../reducel1_variable_dynamic_axes_test.cpp | 59 +++++++++++++++++ .../reducel1_variable_empty_axes_test.cpp | 47 ++++++++++++++ test/onnx/reducel1_empty_axes_test.onnx | Bin 0 -> 190 bytes test/onnx/reducel1_keepdims_clear_test.onnx | Bin 0 -> 209 bytes test/onnx/reducel1_noop_test.onnx | 17 +++++ test/onnx/reducel1_test.onnx | Bin 149 -> 179 bytes ...el1_variable_axes_keepdims_clear_test.onnx | Bin 0 -> 245 bytes .../reducel1_variable_axes_noop_set_test.onnx | 22 +++++++ .../reducel1_variable_dynamic_axes_test.onnx | Bin 0 -> 200 bytes 19 files changed, 429 insertions(+), 36 deletions(-) create mode 100644 test/onnx/parse/reducel1_empty_axes_test.cpp create mode 100644 test/onnx/parse/reducel1_keepdims_clear_test.cpp create mode 100644 test/onnx/parse/reducel1_noop_test.cpp create mode 100644 test/onnx/parse/reducel1_variable_axes_keepdims_clear_test.cpp create mode 100644 test/onnx/parse/reducel1_variable_axes_noop_set_test.cpp create mode 100644 test/onnx/parse/reducel1_variable_axes_test.cpp create mode 100644 test/onnx/parse/reducel1_variable_dynamic_axes_test.cpp create mode 100644 test/onnx/parse/reducel1_variable_empty_axes_test.cpp create mode 100644 test/onnx/reducel1_empty_axes_test.onnx create mode 100644 test/onnx/reducel1_keepdims_clear_test.onnx create mode 100644 test/onnx/reducel1_noop_test.onnx create mode 100644 test/onnx/reducel1_variable_axes_keepdims_clear_test.onnx create mode 100644 test/onnx/reducel1_variable_axes_noop_set_test.onnx create mode 100644 test/onnx/reducel1_variable_dynamic_axes_test.onnx diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 3de31d1ed44..88ee0435b45 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -201,9 +201,9 @@ struct reduce_op : op_name static_cast(*this).output(batch_shape)(val); } - argument compute(const shape& computed_shape, - const std::vector& reduce_axes, - argument& data_arg) const + argument reduce(const shape& computed_shape, + const std::vector& reduce_axes, + argument& data_arg) const { std::vector batch_lens(computed_shape.ndim(), 1); auto arg_lens = data_arg.get_shape().lens(); @@ -226,24 +226,18 @@ struct reduce_op : op_name auto&& data_arg = args[0]; if(not axes.empty()) { - return compute(dyn_out.computed_shape, axes, data_arg); + return reduce(dyn_out.computed_shape, axes, data_arg); } - - std::vector reduce_axes; - if(args.size() == 2) - { - args[1].visit([&](auto&& s) { reduce_axes.assign(s.begin(), s.end()); }); - } - - if(reduce_axes.empty()) - { - reduce_axes.resize(data_arg.get_shape().ndim()); - std::iota(reduce_axes.begin(), reduce_axes.end(), 0); + + if(axes.empty() and args[1].empty()) { + return args[0]; } + std::vector reduce_axes; + args[1].visit([&](auto&& s) { reduce_axes.assign(s.begin(), s.end()); }); const auto result_shape = collapse_reduced_axes(data_arg.get_shape(), reduce_axes); - return compute(result_shape, reduce_axes, data_arg); + return reduce(result_shape, reduce_axes, data_arg); } auto init() const { return zero(); } diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index 9459bc694ec..1021991d57e 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -49,6 +49,7 @@ struct reduce_parser : op_parser std::vector all_axes(args.front()->get_shape().ndim()); std::iota(all_axes.begin(), all_axes.end(), 0); + // Handle axes attribute, constant input axes, and missing both attribute and input cases if(constant_axes.has_value()) { if(noop_with_empty_axes != 0 and constant_axes->empty()) @@ -70,6 +71,7 @@ struct reduce_parser : op_parser return reduce; } + // Handle variable input axes if(keep_dims == 0) { MIGRAPHX_THROW("Keepdims not supported with runtime provided axes"); @@ -120,7 +122,7 @@ struct reduce_parser : op_parser return std::nullopt; } - return parser.parse_value(info.attributes.at(attribute_name)).at(); + return parser.parse_value(info.attributes[attribute_name]).at(); } std::optional> parse_constant_axes(std::vector& args, diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index e1b7f508c8a..49a69904c6c 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -7211,32 +7211,54 @@ def recip_test(): return ([node], [x], [y]) -def reduceop_variable_axes_test(op_name): +def reduceop_test(op_name, axes, keepdims=1, noop_with_empty_axes=0): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) - axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [1]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 6]) + + node = onnx.helper.make_node('ReduceL1', + inputs=['x'], + outputs=['y'], + axes=axes, + keepdims=keepdims, + noop_with_empty_axes=noop_with_empty_axes) + + return ([node], [x], [y]) + + + + +def reduceop_variable_axes_test(op_name, axes_len=1, keepdims=1, noop_with_empty_axes=0): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) + axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [axes_len]) y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 1, 6]) node = onnx.helper.make_node(op_name, inputs=['x', 'axes'], outputs=['y'], - keepdims=1) + keepdims=keepdims, + noop_with_empty_axes=noop_with_empty_axes) return ([node], [x, axes], [y]) @onnx_test() def reducel1_test(): - x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) - y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 6]) - axes = [-2] + return reduceop_test('ReduceL1', [-2]) - node = onnx.helper.make_node('ReduceL1', - inputs=['x'], - outputs=['y'], - axes=axes, - keepdims=0) - return ([node], [x], [y]) +@onnx_test() +def reducel1_keepdims_clear_test(): + return reduceop_test('ReduceL1', [-2], keepdims=0) + + +@onnx_test() +def reducel1_empty_axes_test(): + return reduceop_test('ReduceL1', []) + + +@onnx_test() +def reducel1_noop_test(): + return reduceop_test('ReduceL1', [], noop_with_empty_axes=1) @onnx_test @@ -7272,6 +7294,20 @@ def reducel1_variable_axes_test(): return reduceop_variable_axes_test('ReduceL1') +@onnx_test() +def reducel1_variable_axes_noop_set_test(): + return reduceop_variable_axes_test('ReduceL1', noop_with_empty_axes=1) + +@onnx_test() +def reducel1_variable_axes_keepdims_clear_test(): + return reduceop_variable_axes_test('ReduceL1', keepdims=0) + + +@onnx_test() +def reducel1_variable_dynamic_axes_test(): + return reduceop_variable_axes_test('ReduceL1', None) + + @onnx_test() def reducel2_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) diff --git a/test/onnx/parse/reducel1_empty_axes_test.cpp b/test/onnx/parse/reducel1_empty_axes_test.cpp new file mode 100644 index 00000000000..a764b7f3505 --- /dev/null +++ b/test/onnx/parse/reducel1_empty_axes_test.cpp @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +TEST_CASE(reducel1_empty_axes_test) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + auto abs_x = mm->add_instruction(migraphx::make_op("abs"), x); + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {0, 1, 2, 3}}}), abs_x); + + auto prog = optimize_onnx("reducel1_empty_axes_test.onnx"); + EXPECT(p == prog); +} diff --git a/test/onnx/parse/reducel1_keepdims_clear_test.cpp b/test/onnx/parse/reducel1_keepdims_clear_test.cpp new file mode 100644 index 00000000000..7735513d3bf --- /dev/null +++ b/test/onnx/parse/reducel1_keepdims_clear_test.cpp @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +TEST_CASE(reducel1_keepdims_clear_test) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + auto abs_x = mm->add_instruction(migraphx::make_op("abs"), x); + auto reduce_sum = mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {-2}}}), abs_x); + mm->add_instruction(migraphx::make_op("squeeze", {{"axes", {-2}}}), reduce_sum); + + auto prog = optimize_onnx("reducel1_keepdims_clear_test.onnx"); + EXPECT(p == prog); +} diff --git a/test/onnx/parse/reducel1_noop_test.cpp b/test/onnx/parse/reducel1_noop_test.cpp new file mode 100644 index 00000000000..c206706b769 --- /dev/null +++ b/test/onnx/parse/reducel1_noop_test.cpp @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +TEST_CASE(reducel1_noop_test) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + mm->add_instruction(migraphx::make_op("abs"), x); + + auto prog = optimize_onnx("reducel1_noop_test.onnx"); + EXPECT(p == prog); +} diff --git a/test/onnx/parse/reducel1_test.cpp b/test/onnx/parse/reducel1_test.cpp index abb454a6263..6cd4ef26283 100644 --- a/test/onnx/parse/reducel1_test.cpp +++ b/test/onnx/parse/reducel1_test.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,12 +27,11 @@ TEST_CASE(reducel1_test) { migraphx::program p; - auto* mm = p.get_main_module(); - auto l0 = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); - auto abs_l0 = mm->add_instruction(migraphx::make_op("abs"), l0); - auto sum_l0 = mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {-2}}}), abs_l0); - mm->add_instruction(migraphx::make_op("squeeze", {{"axes", {-2}}}), sum_l0); - auto prog = optimize_onnx("reducel1_test.onnx"); + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + auto abs_x = mm->add_instruction(migraphx::make_op("abs"), x); + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {-2}}}), abs_x); + auto prog = optimize_onnx("reducel1_test.onnx"); EXPECT(p == prog); } diff --git a/test/onnx/parse/reducel1_variable_axes_keepdims_clear_test.cpp b/test/onnx/parse/reducel1_variable_axes_keepdims_clear_test.cpp new file mode 100644 index 00000000000..d628f6f5e50 --- /dev/null +++ b/test/onnx/parse/reducel1_variable_axes_keepdims_clear_test.cpp @@ -0,0 +1,30 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +TEST_CASE(reducel1_variable_axes_keepdims_clear_test) +{ + EXPECT(test::throws( + [&] { migraphx::parse_onnx("reducel1_variable_axes_keepdims_clear_test.onnx"); })); +} diff --git a/test/onnx/parse/reducel1_variable_axes_noop_set_test.cpp b/test/onnx/parse/reducel1_variable_axes_noop_set_test.cpp new file mode 100644 index 00000000000..8a552b8e361 --- /dev/null +++ b/test/onnx/parse/reducel1_variable_axes_noop_set_test.cpp @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +TEST_CASE(reducel1_variable_axes_noop_set_test) +{ + using namespace migraphx; + + program p; + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); + auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); + auto abs_x = mm->add_instruction(make_op("abs"), x); + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, axes); + + auto prog = optimize_onnx("reducel1_variable_axes_noop_set_test.onnx"); + EXPECT(p == prog); +} diff --git a/test/onnx/parse/reducel1_variable_axes_test.cpp b/test/onnx/parse/reducel1_variable_axes_test.cpp new file mode 100644 index 00000000000..66cb98325cd --- /dev/null +++ b/test/onnx/parse/reducel1_variable_axes_test.cpp @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +TEST_CASE(reducel1_variable_axes_test) +{ + using namespace migraphx; + + program p; + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); + auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); + auto abs_x = mm->add_instruction(make_op("abs"), x); + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, axes); + + auto prog = optimize_onnx("reducel1_variable_axes_test.onnx"); + EXPECT(p == prog); +} diff --git a/test/onnx/parse/reducel1_variable_dynamic_axes_test.cpp b/test/onnx/parse/reducel1_variable_dynamic_axes_test.cpp new file mode 100644 index 00000000000..bbcbc440c4a --- /dev/null +++ b/test/onnx/parse/reducel1_variable_dynamic_axes_test.cpp @@ -0,0 +1,59 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +TEST_CASE(reducel1_variable_dynamic_axes_test) +{ + using namespace migraphx; + + program p; + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); + auto abs_x = mm->add_instruction(make_op("abs"), x); + const std::vector axes_dims{{0, 3}}; + auto axes = mm->add_parameter("axes", shape{shape::int64_type, axes_dims}); + + auto reduce_input_axes = + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, axes); + std::vector all_axes(x->get_shape().ndim()); + std::iota(all_axes.begin(), all_axes.end(), 0); + auto all_axes_lit = + mm->add_literal(literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); + auto reduce_all_axes = + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, all_axes_lit); + + auto zero_lit = mm->add_literal(literal{shape{shape::int64_type}, {0u}}); + auto axes_size = mm->add_instruction(make_op("dimensions_of", {{"end", 1}}), axes); + auto is_axes_empty = mm->add_instruction(make_op("equal"), axes_size, zero_lit); + auto is_axes_empty_bc = + mm->add_instruction(make_op("multibroadcast"), is_axes_empty, reduce_all_axes); + auto where = + mm->add_instruction(make_op("where"), is_axes_empty_bc, reduce_all_axes, reduce_input_axes); + mm->add_return({where}); + + onnx_options options; + options.map_dyn_input_dims["axes"] = axes->get_shape().dyn_dims(); + auto prog = parse_onnx("reducel1_variable_dynamic_axes_test.onnx", options); + EXPECT(p == prog); +} diff --git a/test/onnx/parse/reducel1_variable_empty_axes_test.cpp b/test/onnx/parse/reducel1_variable_empty_axes_test.cpp new file mode 100644 index 00000000000..a18cc80993a --- /dev/null +++ b/test/onnx/parse/reducel1_variable_empty_axes_test.cpp @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +TEST_CASE(reducel1_variable_empty_axes_test) +{ + using namespace migraphx; + program p; + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); + auto abs_x = mm->add_instruction(make_op("abs"), x); + auto axes = mm->add_parameter("axes", shape{shape::int64_type, {0}}); + + std::vector all_axes(x->get_shape().ndim()); + std::iota(all_axes.begin(), all_axes.end(), 0); + auto all_axes_lit = + mm->add_literal(literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); + auto reduce_all_axes = + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, all_axes_lit); + mm->add_return({reduce_all_axes}); + + onnx_options options; + options.map_input_dims["axes"] = axes->get_shape().lens(); + auto prog = parse_onnx("reducel1_variable_axes_test.onnx", options); + EXPECT(p == prog); +} diff --git a/test/onnx/reducel1_empty_axes_test.onnx b/test/onnx/reducel1_empty_axes_test.onnx new file mode 100644 index 0000000000000000000000000000000000000000..9f9149d2afae6419d56739ea2b0eff37980a12f8 GIT binary patch literal 190 zcmd} z0#dPnkzI?Qiz7QVwIC%kw^)L40V9)^G?z$TettoGd1grll4%kQKuO&8L`j1z5#ti! mU=$MIV&Y&1Viq7~1!A@&aW2M6At5dSpd=5HB%2eHfG_}7@GYbO literal 0 HcmV?d00001 diff --git a/test/onnx/reducel1_keepdims_clear_test.onnx b/test/onnx/reducel1_keepdims_clear_test.onnx new file mode 100644 index 0000000000000000000000000000000000000000..ae250d4de015f4df69684718e690d8de3719b343 GIT binary patch literal 209 zcmdT|PtHkAEQ&8lEiSQI#mE)H#aJQ4SgFJj1Xk!{ zs3pS1l30;i?C|eD6fiDeWY^;7;((bT!LWdlNlThbBriX|Aig}aBqKgGx1gjl9;6K{ xiQn2NX^@>_Tp}EdLIPY&9Lzw>0>rF9%$6k1#aJmM#3cZf|?0K&&2`LA;GYKkx5IMOC&EpzaYLmvm_%vHMgLo5^OG5 zk`zm$q=7aHiE)W=FbWB9F>x>hF$)m00x?^Z5Y#PPTpS$iLLhO*B%p>$EE*U=8l0E} FgaJVhJ|F-9 literal 0 HcmV?d00001 diff --git a/test/onnx/reducel1_variable_axes_noop_set_test.onnx b/test/onnx/reducel1_variable_axes_noop_set_test.onnx new file mode 100644 index 00000000000..2dc653fba40 --- /dev/null +++ b/test/onnx/reducel1_variable_axes_noop_set_test.onnx @@ -0,0 +1,22 @@ + $reducel1_variable_axes_noop_set_test:Ί +D +x +axesy"ReduceL1* +keepdims * +noop_with_empty_axes $reducel1_variable_axes_noop_set_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducel1_variable_dynamic_axes_test.onnx b/test/onnx/reducel1_variable_dynamic_axes_test.onnx new file mode 100644 index 0000000000000000000000000000000000000000..6e8ee5524cfdf254f1dbc2e6691336187437ab78 GIT binary patch literal 200 zcmd+&(w;^*SXPE9RH$;>U5U|hh+M3jM1(m>OM#JEH_7=;A5m^he$m<5Pg hftW2y0BR2h7aIq=5EBR<17Uhf}EE`$I8 literal 0 HcmV?d00001 From 71d00e62cba061794df46f555ca4938583f7f79d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Mon, 29 Jan 2024 16:19:54 +0000 Subject: [PATCH 15/25] Implement parse tests for ReduceSum --- test/onnx/gen_onnx.py | 129 ++++++------------ .../parse/reducel1_keepdims_clear_test.cpp | 37 ----- test/onnx/parse/reducel1_noop_test.cpp | 35 ----- test/onnx/parse/reducel1_test.cpp | 13 +- ...sum_variable_axes_keepdims_clear_test.cpp} | 4 +- ...t.cpp => reducesum_variable_axes_test.cpp} | 7 +- ... reducesum_variable_dynamic_axes_test.cpp} | 14 +- ...=> reducesum_variable_empty_axes_test.cpp} | 13 +- test/onnx/reducel1_test.onnx | Bin 179 -> 149 bytes test/onnx/reducel1_variable_axes_test.onnx | 21 --- ...sum_variable_axes_keepdims_clear_test.onnx | Bin 0 -> 248 bytes ... => reducesum_variable_axes_noop_test.cpp} | 7 +- .../reducesum_variable_axes_noop_test.onnx | 22 +++ test/onnx/reducesum_variable_axes_test.onnx | Bin 189 -> 218 bytes .../reducesum_variable_dynamic_axes_test.onnx | Bin 0 -> 232 bytes ...sum_variable_dynamic_axes_verify_test.onnx | Bin 0 -> 182 bytes .../reducesum_variable_dynamic_axes_test.cpp} | 29 ++-- 17 files changed, 107 insertions(+), 224 deletions(-) delete mode 100644 test/onnx/parse/reducel1_keepdims_clear_test.cpp delete mode 100644 test/onnx/parse/reducel1_noop_test.cpp rename test/onnx/parse/{reducel1_variable_axes_keepdims_clear_test.cpp => reducesum_variable_axes_keepdims_clear_test.cpp} (89%) rename test/onnx/parse/{reducel1_variable_axes_test.cpp => reducesum_variable_axes_test.cpp} (86%) rename test/onnx/parse/{reducel1_variable_dynamic_axes_test.cpp => reducesum_variable_dynamic_axes_test.cpp} (84%) rename test/onnx/parse/{reducel1_variable_empty_axes_test.cpp => reducesum_variable_empty_axes_test.cpp} (80%) delete mode 100644 test/onnx/reducel1_variable_axes_test.onnx create mode 100644 test/onnx/reducesum_variable_axes_keepdims_clear_test.onnx rename test/onnx/{parse/reducel1_variable_axes_noop_set_test.cpp => reducesum_variable_axes_noop_test.cpp} (85%) create mode 100644 test/onnx/reducesum_variable_axes_noop_test.onnx create mode 100644 test/onnx/reducesum_variable_dynamic_axes_test.onnx create mode 100644 test/onnx/reducesum_variable_dynamic_axes_verify_test.onnx rename test/onnx/{parse/reducel1_empty_axes_test.cpp => verify/reducesum_variable_dynamic_axes_test.cpp} (59%) diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index 49a69904c6c..3842b09a460 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -7211,22 +7211,6 @@ def recip_test(): return ([node], [x], [y]) -def reduceop_test(op_name, axes, keepdims=1, noop_with_empty_axes=0): - x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) - y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 6]) - - node = onnx.helper.make_node('ReduceL1', - inputs=['x'], - outputs=['y'], - axes=axes, - keepdims=keepdims, - noop_with_empty_axes=noop_with_empty_axes) - - return ([node], [x], [y]) - - - - def reduceop_variable_axes_test(op_name, axes_len=1, keepdims=1, noop_with_empty_axes=0): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [axes_len]) @@ -7243,22 +7227,17 @@ def reduceop_variable_axes_test(op_name, axes_len=1, keepdims=1, noop_with_empty @onnx_test() def reducel1_test(): - return reduceop_test('ReduceL1', [-2]) - - -@onnx_test() -def reducel1_keepdims_clear_test(): - return reduceop_test('ReduceL1', [-2], keepdims=0) - - -@onnx_test() -def reducel1_empty_axes_test(): - return reduceop_test('ReduceL1', []) + x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 6]) + axes = [-2] + node = onnx.helper.make_node('ReduceL1', + inputs=['x'], + outputs=['y'], + axes=axes, + keepdims=0) -@onnx_test() -def reducel1_noop_test(): - return reduceop_test('ReduceL1', [], noop_with_empty_axes=1) + return ([node], [x], [y]) @onnx_test @@ -7289,25 +7268,6 @@ def reducel1_dyn_noaxes_test(): return ([node], [x], [y]) -@onnx_test() -def reducel1_variable_axes_test(): - return reduceop_variable_axes_test('ReduceL1') - - -@onnx_test() -def reducel1_variable_axes_noop_set_test(): - return reduceop_variable_axes_test('ReduceL1', noop_with_empty_axes=1) - -@onnx_test() -def reducel1_variable_axes_keepdims_clear_test(): - return reduceop_variable_axes_test('ReduceL1', keepdims=0) - - -@onnx_test() -def reducel1_variable_dynamic_axes_test(): - return reduceop_variable_axes_test('ReduceL1', None) - - @onnx_test() def reducel2_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -7323,11 +7283,6 @@ def reducel2_test(): return ([node], [x], [y]) -@onnx_test() -def reducel2_variable_axes_test(): - return reduceop_variable_axes_test('ReduceL2') - - @onnx_test() def reduce_log_sum_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -7343,11 +7298,6 @@ def reduce_log_sum_test(): return ([node], [x], [y]) -@onnx_test() -def reduce_log_sum_variable_axes_test(): - return reduceop_variable_axes_test('ReduceLogSum') - - @onnx_test() def reduce_log_sum_exp_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -7363,11 +7313,6 @@ def reduce_log_sum_exp_test(): return ([node], [x], [y]) -@onnx_test() -def reduce_log_sum_exp_variable_axes_test(): - return reduceop_variable_axes_test('ReduceLogSumExp') - - @onnx_test() def reducemax_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -7399,11 +7344,6 @@ def reducemax_dyn_test(): return ([node], [x], [y]) -@onnx_test() -def reducemax_variable_axes_test(): - return reduceop_variable_axes_test('ReduceMax') - - @onnx_test() def reducemean_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -7434,11 +7374,6 @@ def reducemean_keepdims_test(): return ([node], [x], [y]) -@onnx_test() -def reducemean_variable_axes_test(): - return reduceop_variable_axes_test('ReduceMean') - - @onnx_test() def reducemin_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -7454,11 +7389,6 @@ def reducemin_test(): return ([node], [x], [y]) -@onnx_test() -def reducemin_variable_axes_test(): - return reduceop_variable_axes_test('ReduceMin') - - @onnx_test() def reduceprod_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -7474,21 +7404,15 @@ def reduceprod_test(): return ([node], [x], [y]) -@onnx_test() -def reduceprod_variable_axes_test(): - return reduceop_variable_axes_test('ReduceProd') - - @onnx_test() def reducesum_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 1, 6]) - axes = [2] node = onnx.helper.make_node('ReduceSum', inputs=['x'], outputs=['y'], - axes=axes, + axes=[2], keepdims=0) return ([node], [x], [y]) @@ -7567,6 +7491,34 @@ def reducesum_variable_axes_test(): return reduceop_variable_axes_test('ReduceSum') +@onnx_test() +def reducesum_variable_axes_noop_test(): + return reduceop_variable_axes_test('ReduceSum', noop_with_empty_axes=1) + + +@onnx_test() +def reducesum_variable_axes_keepdims_clear_test(): + return reduceop_variable_axes_test('ReduceSum', keepdims=0) + + +@onnx_test() +def reducesum_variable_dynamic_axes_test(): + return reduceop_variable_axes_test('ReduceSum', None) + + +@onnx_test() +def reducesum_variable_dynamic_axes_verify_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [2, 2, 2]) + axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [None]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [None]) + + node = onnx.helper.make_node('ReduceSum', + inputs=['x', 'axes'], + outputs=['y']) + + return ([node], [x, axes], [y]) + + @onnx_test() def reducesum_square_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) @@ -7582,11 +7534,6 @@ def reducesum_square_test(): return ([node], [x], [y]) -@onnx_test() -def reducesum_square_variable_axes_test(): - return reduceop_variable_axes_test('ReduceSumSquare') - - @onnx_test() def reshape_test(): x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [4, 2, 3]) diff --git a/test/onnx/parse/reducel1_keepdims_clear_test.cpp b/test/onnx/parse/reducel1_keepdims_clear_test.cpp deleted file mode 100644 index 7735513d3bf..00000000000 --- a/test/onnx/parse/reducel1_keepdims_clear_test.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include - -TEST_CASE(reducel1_keepdims_clear_test) -{ - migraphx::program p; - auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); - auto abs_x = mm->add_instruction(migraphx::make_op("abs"), x); - auto reduce_sum = mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {-2}}}), abs_x); - mm->add_instruction(migraphx::make_op("squeeze", {{"axes", {-2}}}), reduce_sum); - - auto prog = optimize_onnx("reducel1_keepdims_clear_test.onnx"); - EXPECT(p == prog); -} diff --git a/test/onnx/parse/reducel1_noop_test.cpp b/test/onnx/parse/reducel1_noop_test.cpp deleted file mode 100644 index c206706b769..00000000000 --- a/test/onnx/parse/reducel1_noop_test.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include - -TEST_CASE(reducel1_noop_test) -{ - migraphx::program p; - auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); - mm->add_instruction(migraphx::make_op("abs"), x); - - auto prog = optimize_onnx("reducel1_noop_test.onnx"); - EXPECT(p == prog); -} diff --git a/test/onnx/parse/reducel1_test.cpp b/test/onnx/parse/reducel1_test.cpp index 6cd4ef26283..abb454a6263 100644 --- a/test/onnx/parse/reducel1_test.cpp +++ b/test/onnx/parse/reducel1_test.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,11 +27,12 @@ TEST_CASE(reducel1_test) { migraphx::program p; - auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); - auto abs_x = mm->add_instruction(migraphx::make_op("abs"), x); - mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {-2}}}), abs_x); - + auto* mm = p.get_main_module(); + auto l0 = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + auto abs_l0 = mm->add_instruction(migraphx::make_op("abs"), l0); + auto sum_l0 = mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {-2}}}), abs_l0); + mm->add_instruction(migraphx::make_op("squeeze", {{"axes", {-2}}}), sum_l0); auto prog = optimize_onnx("reducel1_test.onnx"); + EXPECT(p == prog); } diff --git a/test/onnx/parse/reducel1_variable_axes_keepdims_clear_test.cpp b/test/onnx/parse/reducesum_variable_axes_keepdims_clear_test.cpp similarity index 89% rename from test/onnx/parse/reducel1_variable_axes_keepdims_clear_test.cpp rename to test/onnx/parse/reducesum_variable_axes_keepdims_clear_test.cpp index d628f6f5e50..d7ca00f188a 100644 --- a/test/onnx/parse/reducel1_variable_axes_keepdims_clear_test.cpp +++ b/test/onnx/parse/reducesum_variable_axes_keepdims_clear_test.cpp @@ -23,8 +23,8 @@ */ #include -TEST_CASE(reducel1_variable_axes_keepdims_clear_test) +TEST_CASE(reducesum_variable_axes_keepdims_clear_test) { EXPECT(test::throws( - [&] { migraphx::parse_onnx("reducel1_variable_axes_keepdims_clear_test.onnx"); })); + [&] { migraphx::parse_onnx("reducesum_variable_axes_keepdims_clear_test.onnx"); })); } diff --git a/test/onnx/parse/reducel1_variable_axes_test.cpp b/test/onnx/parse/reducesum_variable_axes_test.cpp similarity index 86% rename from test/onnx/parse/reducel1_variable_axes_test.cpp rename to test/onnx/parse/reducesum_variable_axes_test.cpp index 66cb98325cd..978ca8f0f27 100644 --- a/test/onnx/parse/reducel1_variable_axes_test.cpp +++ b/test/onnx/parse/reducesum_variable_axes_test.cpp @@ -23,7 +23,7 @@ */ #include -TEST_CASE(reducel1_variable_axes_test) +TEST_CASE(reducesum_variable_axes_test) { using namespace migraphx; @@ -31,9 +31,8 @@ TEST_CASE(reducel1_variable_axes_test) auto* mm = p.get_main_module(); auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); - auto abs_x = mm->add_instruction(make_op("abs"), x); - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, axes); + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, axes); - auto prog = optimize_onnx("reducel1_variable_axes_test.onnx"); + auto prog = optimize_onnx("reducesum_variable_axes_test.onnx"); EXPECT(p == prog); } diff --git a/test/onnx/parse/reducel1_variable_dynamic_axes_test.cpp b/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp similarity index 84% rename from test/onnx/parse/reducel1_variable_dynamic_axes_test.cpp rename to test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp index bbcbc440c4a..db684c6f59e 100644 --- a/test/onnx/parse/reducel1_variable_dynamic_axes_test.cpp +++ b/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp @@ -23,25 +23,23 @@ */ #include -TEST_CASE(reducel1_variable_dynamic_axes_test) +TEST_CASE(reducesum_variable_dynamic_axes_test) { using namespace migraphx; program p; - auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); - auto abs_x = mm->add_instruction(make_op("abs"), x); + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); const std::vector axes_dims{{0, 3}}; auto axes = mm->add_parameter("axes", shape{shape::int64_type, axes_dims}); - auto reduce_input_axes = - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, axes); + auto reduce_input_axes = mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, axes); std::vector all_axes(x->get_shape().ndim()); std::iota(all_axes.begin(), all_axes.end(), 0); auto all_axes_lit = mm->add_literal(literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); auto reduce_all_axes = - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, all_axes_lit); + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, all_axes_lit); auto zero_lit = mm->add_literal(literal{shape{shape::int64_type}, {0u}}); auto axes_size = mm->add_instruction(make_op("dimensions_of", {{"end", 1}}), axes); @@ -54,6 +52,6 @@ TEST_CASE(reducel1_variable_dynamic_axes_test) onnx_options options; options.map_dyn_input_dims["axes"] = axes->get_shape().dyn_dims(); - auto prog = parse_onnx("reducel1_variable_dynamic_axes_test.onnx", options); + auto prog = parse_onnx("reducesum_variable_dynamic_axes_test.onnx", options); EXPECT(p == prog); } diff --git a/test/onnx/parse/reducel1_variable_empty_axes_test.cpp b/test/onnx/parse/reducesum_variable_empty_axes_test.cpp similarity index 80% rename from test/onnx/parse/reducel1_variable_empty_axes_test.cpp rename to test/onnx/parse/reducesum_variable_empty_axes_test.cpp index a18cc80993a..a1e72537dc8 100644 --- a/test/onnx/parse/reducel1_variable_empty_axes_test.cpp +++ b/test/onnx/parse/reducesum_variable_empty_axes_test.cpp @@ -23,25 +23,24 @@ */ #include -TEST_CASE(reducel1_variable_empty_axes_test) +TEST_CASE(reducesum_variable_empty_axes_test) { using namespace migraphx; program p; - auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); - auto abs_x = mm->add_instruction(make_op("abs"), x); - auto axes = mm->add_parameter("axes", shape{shape::int64_type, {0}}); + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); + auto axes = mm->add_parameter("axes", shape{shape::int64_type, {0}}); std::vector all_axes(x->get_shape().ndim()); std::iota(all_axes.begin(), all_axes.end(), 0); auto all_axes_lit = mm->add_literal(literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); auto reduce_all_axes = - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, all_axes_lit); + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, all_axes_lit); mm->add_return({reduce_all_axes}); onnx_options options; options.map_input_dims["axes"] = axes->get_shape().lens(); - auto prog = parse_onnx("reducel1_variable_axes_test.onnx", options); + auto prog = parse_onnx("reducesum_variable_axes_test.onnx", options); EXPECT(p == prog); } diff --git a/test/onnx/reducel1_test.onnx b/test/onnx/reducel1_test.onnx index 6105475db14290c2f6742dfc8aad098846758dc0..b72af05cfdffc9e15748dbc2e3f0525f16ac3176 100644 GIT binary patch delta 34 pcmdnYIF(V9gH4FHC^e-tIW@;Hz9hA{#Hx -TEST_CASE(reducel1_variable_axes_noop_set_test) +TEST_CASE(reducesum_variable_axes_noop_set_test) { using namespace migraphx; @@ -31,9 +31,8 @@ TEST_CASE(reducel1_variable_axes_noop_set_test) auto* mm = p.get_main_module(); auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); - auto abs_x = mm->add_instruction(make_op("abs"), x); - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), abs_x, axes); + mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, axes); - auto prog = optimize_onnx("reducel1_variable_axes_noop_set_test.onnx"); + auto prog = optimize_onnx("reducesum_variable_axes_noop_set_test.onnx"); EXPECT(p == prog); } diff --git a/test/onnx/reducesum_variable_axes_noop_test.onnx b/test/onnx/reducesum_variable_axes_noop_test.onnx new file mode 100644 index 00000000000..e3e9e8fd408 --- /dev/null +++ b/test/onnx/reducesum_variable_axes_noop_test.onnx @@ -0,0 +1,22 @@ + !reducesum_variable_axes_noop_test:Έ +E +x +axesy" ReduceSum* +keepdims * +noop_with_empty_axes !reducesum_variable_axes_noop_testZ +x + + + + +Z +axes + + +b +y + + + + +B \ No newline at end of file diff --git a/test/onnx/reducesum_variable_axes_test.onnx b/test/onnx/reducesum_variable_axes_test.onnx index 00cffbd9cfdfabc7850db0aba5768c781cc13178..d2a2bc4a2c418e7595fa90b37fcbd8943a37c7c3 100644 GIT binary patch delta 44 zcmdnXc#Cm@BFkn*F4u{w8d6%)Tq1e-`33RinI#$VsksFumGOxcsl^fu6TON7HPsG? delta 17 Ycmcb`xR-H)BFi*JE{%z*8WXb$05Qh}VE_OC diff --git a/test/onnx/reducesum_variable_dynamic_axes_test.onnx b/test/onnx/reducesum_variable_dynamic_axes_test.onnx new file mode 100644 index 0000000000000000000000000000000000000000..c956ac17e9526acb905b4403f54449d86d0fee95 GIT binary patch literal 232 zcmdb=-ElA1CEtX(hz{sQ}%_WkTpI;DPo>`I+pPE}xQVBLm zf&nN=oPAN!K+A;0xI{P@g#@^mIGBN$1&CRJm@P^G>I@DpHV$?nCN72~pz=yA${9h* IotOlK0eDe5e*gdg literal 0 HcmV?d00001 diff --git a/test/onnx/reducesum_variable_dynamic_axes_verify_test.onnx b/test/onnx/reducesum_variable_dynamic_axes_verify_test.onnx new file mode 100644 index 0000000000000000000000000000000000000000..b37ab32e73017b3adcbdc4e2bdb01da549393069 GIT binary patch literal 182 zcmd +#include #include -TEST_CASE(reducel1_empty_axes_test) +TEST_CASE(bla) { - migraphx::program p; - auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); - auto abs_x = mm->add_instruction(migraphx::make_op("abs"), x); - mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {0, 1, 2, 3}}}), abs_x); + using namespace migraphx; + onnx_options options; + const std::vector axes_dims{{0, 3}}; + options.map_dyn_input_dims["axes"] = axes_dims; + program p = parse_onnx("reducesum_variable_dynamic_axes_verify_test.onnx", options); + p.compile(make_target("ref")); - auto prog = optimize_onnx("reducel1_empty_axes_test.onnx"); - EXPECT(p == prog); + parameter_map pm; + shape x_shape{shape::float_type, {2, 2, 2}}; + std::vector x(x_shape.elements()); + std::iota(x.begin(), x.end(), 0); + pm["x"] = argument(x_shape, x.data()); + + std::vector axes{1}; + pm["axes"] = argument(shape{shape::int64_type, {1}}, axes.data()); + + auto result = p.eval(pm); } From 2e324f82fe2dfd470e36832fd009c0998a27067b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Mon, 29 Jan 2024 16:25:15 +0000 Subject: [PATCH 16/25] Delete ReduceL1 onnx test files --- test/onnx/reducel1_dyn_noaxes_test.onnx | Bin 125 -> 0 bytes test/onnx/reducel1_empty_axes_test.onnx | Bin 190 -> 0 bytes test/onnx/reducel1_keepdims_clear_test.onnx | Bin 209 -> 0 bytes test/onnx/reducel1_noop_test.onnx | 17 -------------- ...el1_variable_axes_keepdims_clear_test.onnx | Bin 245 -> 0 bytes .../reducel1_variable_axes_noop_set_test.onnx | 22 ------------------ .../reducel1_variable_dynamic_axes_test.onnx | Bin 200 -> 0 bytes 7 files changed, 39 deletions(-) delete mode 100644 test/onnx/reducel1_dyn_noaxes_test.onnx delete mode 100644 test/onnx/reducel1_empty_axes_test.onnx delete mode 100644 test/onnx/reducel1_keepdims_clear_test.onnx delete mode 100644 test/onnx/reducel1_noop_test.onnx delete mode 100644 test/onnx/reducel1_variable_axes_keepdims_clear_test.onnx delete mode 100644 test/onnx/reducel1_variable_axes_noop_set_test.onnx delete mode 100644 test/onnx/reducel1_variable_dynamic_axes_test.onnx diff --git a/test/onnx/reducel1_dyn_noaxes_test.onnx b/test/onnx/reducel1_dyn_noaxes_test.onnx deleted file mode 100644 index 9f1a76a21de88eb1f7b83cba03fbfab5946d4b34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125 zcmd;J7m_GSO({)I%`uEmsmzPd%TKIGEsifqEiSQ&=2GNhtPoU5U|7J&gj;(QFGw>77aIqo5EB} z0#dPnkzI?Qiz7QVwIC%kw^)L40V9)^G?z$TettoGd1grll4%kQKuO&8L`j1z5#ti! mU=$MIV&Y&1Viq7~1!A@&aW2M6At5dSpd=5HB%2eHfG_}7@GYbO diff --git a/test/onnx/reducel1_keepdims_clear_test.onnx b/test/onnx/reducel1_keepdims_clear_test.onnx deleted file mode 100644 index ae250d4de015f4df69684718e690d8de3719b343..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmdT|PtHkAEQ&8lEiSQI#mE)H#aJQ4SgFJj1Xk!{ zs3pS1l30;i?C|eD6fiDeWY^;7;((bT!LWdlNlThbBriX|Aig}aBqKgGx1gjl9;6K{ xiQn2NX^@>_Tp}EdLIPY&9Lzw>0>rF9%$6k1#aJmM#3cZf|?0K&&2`LA;GYKkx5IMOC&EpzaYLmvm_%vHMgLo5^OG5 zk`zm$q=7aHiE)W=FbWB9F>x>hF$)m00x?^Z5Y#PPTpS$iLLhO*B%p>$EE*U=8l0E} FgaJVhJ|F-9 diff --git a/test/onnx/reducel1_variable_axes_noop_set_test.onnx b/test/onnx/reducel1_variable_axes_noop_set_test.onnx deleted file mode 100644 index 2dc653fba40..00000000000 --- a/test/onnx/reducel1_variable_axes_noop_set_test.onnx +++ /dev/null @@ -1,22 +0,0 @@ - $reducel1_variable_axes_noop_set_test:Ί -D -x -axesy"ReduceL1* -keepdims * -noop_with_empty_axes $reducel1_variable_axes_noop_set_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reducel1_variable_dynamic_axes_test.onnx b/test/onnx/reducel1_variable_dynamic_axes_test.onnx deleted file mode 100644 index 6e8ee5524cfdf254f1dbc2e6691336187437ab78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200 zcmd+&(w;^*SXPE9RH$;>U5U|hh+M3jM1(m>OM#JEH_7=;A5m^he$m<5Pg hftW2y0BR2h7aIq=5EBR<17Uhf}EE`$I8 From 05338d47995ca31be28c109adeb54c6969525168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Mon, 29 Jan 2024 16:33:37 +0000 Subject: [PATCH 17/25] Update test name --- test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp b/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp index 9335da92d0f..df3f9b4da05 100644 --- a/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp +++ b/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp @@ -26,7 +26,7 @@ #include #include -TEST_CASE(bla) +TEST_CASE(reducesum_variable_dynamic_axes_test) { using namespace migraphx; onnx_options options; From 399cde5fd94a325ec27c8ca2e6f569666bbd51bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 7 Feb 2024 11:23:10 +0000 Subject: [PATCH 18/25] Update Where operator to handle scalar predicate --- src/include/migraphx/op/reduce_op.hpp | 2 +- src/include/migraphx/op/where.hpp | 22 +++++++++++---- src/onnx/parse_reduce_op.cpp | 8 ++---- .../reducesum_variable_dynamic_axes_test.cpp | 28 ++++++++++++++++--- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 88ee0435b45..9ff067ba6cc 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/include/migraphx/op/where.hpp b/src/include/migraphx/op/where.hpp index 8c58deaa207..d0f94c312db 100644 --- a/src/include/migraphx/op/where.hpp +++ b/src/include/migraphx/op/where.hpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -42,7 +42,13 @@ struct where shape compute_shape(std::vector inputs) const { - check_shapes{inputs, *this, true}.has(3).same_dims(); + check_shapes shape_checker{inputs, *this, true}; + shape_checker.has(3); + if(auto s = inputs[0]; not s.dynamic() and s.elements() == 1) + check_shapes{std::next(inputs.begin()), inputs.end(), *this, true}.same_dims(); + else + shape_checker.same_dims(); + auto s1 = inputs.at(1); auto s2 = inputs.at(2); if(s1.dynamic() or s2.dynamic()) @@ -71,12 +77,18 @@ struct where } } - argument compute(const dyn_output& dyn_out, std::vector args) const + argument compute(shape output_shape, std::vector args) const { - argument result{dyn_out.computed_shape}; + if(auto s = args[0].get_shape(); not s.dynamic() and s.elements() == 1) + return args[args[0].at() ? 1 : 2].copy(); + + if(output_shape.dynamic()) + output_shape = compute_shape(to_shapes(args)); + argument result{output_shape}; + visit_all(result, args[1], args[2])([&](auto output, const auto x, const auto y) { args[0].visit([&](const auto condition) { - par_for(dyn_out.computed_shape.elements(), + par_for(output_shape.elements(), [&](auto i) { output[i] = condition[i] ? x[i] : y[i]; }); }); }); diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index 1021991d57e..9917516ab57 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -90,14 +90,12 @@ struct reduce_parser : op_parser auto all_axes_lit = info.add_literal( literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); auto reduce_all_axes = info.add_instruction(reduce_op, args[0], all_axes_lit); - auto zero = info.add_literal(literal{shape{shape::type_t::int64_type}, {0u}}); + auto zero = info.add_literal(literal{shape{shape::type_t::int64_type, {1}, {0}}, {0u}}); auto axes_size = info.add_instruction(make_op("dimensions_of", {{"end", 1}}), args[1]); - auto is_axes_empty = info.add_instruction(make_op("equal"), axes_size, zero); - auto is_axes_empty_bc = - info.add_instruction(make_op("multibroadcast"), is_axes_empty, reduce_all_axes); + auto is_axes_empty = info.add_instruction(make_op("equal"), zero, axes_size); return info.add_instruction( - make_op("where"), is_axes_empty_bc, reduce_all_axes, reduce_input_axes); + make_op("where"), is_axes_empty, reduce_all_axes, reduce_input_axes); } else if(args[1]->get_shape().elements() == 0) { diff --git a/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp b/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp index df3f9b4da05..e1932642312 100644 --- a/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp +++ b/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,8 @@ #include #include -TEST_CASE(reducesum_variable_dynamic_axes_test) +std::vector reducesum_variable_dynamic_axes_test_base(migraphx::shape axes_shape, + std::vector axes_data) { using namespace migraphx; onnx_options options; @@ -42,7 +43,26 @@ TEST_CASE(reducesum_variable_dynamic_axes_test) pm["x"] = argument(x_shape, x.data()); std::vector axes{1}; - pm["axes"] = argument(shape{shape::int64_type, {1}}, axes.data()); + pm["axes"] = argument(axes_shape, axes_data.data()); + + auto result = p.eval(pm).back(); + std::vector result_vector; + result.visit([&](auto output) { result_vector.assign(output.begin(), output.end()); }); + return result_vector; +} + +TEST_CASE(reducesum_variable_dynamic_axes_test) +{ + auto result = reducesum_variable_dynamic_axes_test_base({migraphx::shape::int64_type, {1}}, + std::vector{1}); + std::vector gold{2, 4, 10, 12}; + EXPECT(result == gold); +} - auto result = p.eval(pm); +TEST_CASE(reducesum_variable_dynamic_axes_empty_test) +{ + auto result = reducesum_variable_dynamic_axes_test_base({migraphx::shape::int64_type, {0}}, + std::vector{}); + std::vector gold{28}; + EXPECT(result == gold); } From 95fa52e0ffc2a1979193e348200cad939a39583c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 7 Feb 2024 12:34:42 +0000 Subject: [PATCH 19/25] Implement additional tests, fix parsing and licensing --- src/include/migraphx/op/reduce_op.hpp | 5 +- src/onnx/parse_reduce_op.cpp | 21 ++----- .../parse/reducesum_variable_axes_test.cpp | 6 +- .../reducesum_variable_dynamic_axes_test.cpp | 4 +- test/onnx/reducel1_dyn_noaxes_test.onnx | Bin 0 -> 125 bytes .../reducesum_variable_axes_noop_test.cpp | 6 +- .../reducesum_variable_dynamic_axes_test.cpp | 17 +++--- test/op_shape_test.cpp | 2 +- test/ref/reduce_max.cpp | 2 +- test/ref/reduce_mean.cpp | 2 +- test/ref/reduce_min.cpp | 2 +- test/ref/reduce_prod.cpp | 2 +- test/ref/reduce_sum.cpp | 52 +++++++++++++++++- 13 files changed, 79 insertions(+), 42 deletions(-) create mode 100644 test/onnx/reducel1_dyn_noaxes_test.onnx diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 9ff067ba6cc..f05c8f8e26a 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -228,8 +228,9 @@ struct reduce_op : op_name { return reduce(dyn_out.computed_shape, axes, data_arg); } - - if(axes.empty() and args[1].empty()) { + + if(axes.empty() and args[1].empty()) + { return args[0]; } diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index 9917516ab57..e3871004653 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -53,36 +53,29 @@ struct reduce_parser : op_parser if(constant_axes.has_value()) { if(noop_with_empty_axes != 0 and constant_axes->empty()) - { return args[0]; - } if(noop_with_empty_axes == 0 and constant_axes->empty()) - { constant_axes = all_axes; - } auto reduce = info.add_instruction(make_op(op_name, {{"axes", *constant_axes}}), args[0]); + if(keep_dims == 0) - { return info.add_instruction(make_op("squeeze", {{"axes", *constant_axes}}), reduce); - } + return reduce; } // Handle variable input axes if(keep_dims == 0) - { MIGRAPHX_THROW("Keepdims not supported with runtime provided axes"); - } + // Empty axes attribute indicates to the operator to look for axes in the inputs auto reduce_op = make_op(op_name, {{"axes", {}}}); if(noop_with_empty_axes != 0) - { return info.add_instruction(reduce_op, args); - } if(args[1]->get_shape().dynamic()) { @@ -90,9 +83,9 @@ struct reduce_parser : op_parser auto all_axes_lit = info.add_literal( literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); auto reduce_all_axes = info.add_instruction(reduce_op, args[0], all_axes_lit); - auto zero = info.add_literal(literal{shape{shape::type_t::int64_type, {1}, {0}}, {0u}}); + auto zero = info.add_literal(literal{shape{shape::type_t::int64_type}, {0u}}); auto axes_size = info.add_instruction(make_op("dimensions_of", {{"end", 1}}), args[1]); - auto is_axes_empty = info.add_instruction(make_op("equal"), zero, axes_size); + auto is_axes_empty = info.add_instruction(make_op("equal"), axes_size, zero); return info.add_instruction( make_op("where"), is_axes_empty, reduce_all_axes, reduce_input_axes); @@ -116,9 +109,7 @@ struct reduce_parser : op_parser onnx_parser::node_info& info) const { if(not contains(info.attributes, attribute_name)) - { return std::nullopt; - } return parser.parse_value(info.attributes[attribute_name]).at(); } @@ -130,9 +121,7 @@ struct reduce_parser : op_parser if(args.size() == 2) { if(not args[1]->can_eval()) - { return std::nullopt; - } args[1]->eval().visit([&](auto s) { axes.assign(s.begin(), s.end()); }); } else if(contains(info.attributes, "axes")) diff --git a/test/onnx/parse/reducesum_variable_axes_test.cpp b/test/onnx/parse/reducesum_variable_axes_test.cpp index 978ca8f0f27..ef8c0fdec69 100644 --- a/test/onnx/parse/reducesum_variable_axes_test.cpp +++ b/test/onnx/parse/reducesum_variable_axes_test.cpp @@ -28,9 +28,9 @@ TEST_CASE(reducesum_variable_axes_test) using namespace migraphx; program p; - auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); - auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); + auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, axes); auto prog = optimize_onnx("reducesum_variable_axes_test.onnx"); diff --git a/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp b/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp index db684c6f59e..b101ee7bb59 100644 --- a/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp +++ b/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp @@ -44,10 +44,8 @@ TEST_CASE(reducesum_variable_dynamic_axes_test) auto zero_lit = mm->add_literal(literal{shape{shape::int64_type}, {0u}}); auto axes_size = mm->add_instruction(make_op("dimensions_of", {{"end", 1}}), axes); auto is_axes_empty = mm->add_instruction(make_op("equal"), axes_size, zero_lit); - auto is_axes_empty_bc = - mm->add_instruction(make_op("multibroadcast"), is_axes_empty, reduce_all_axes); auto where = - mm->add_instruction(make_op("where"), is_axes_empty_bc, reduce_all_axes, reduce_input_axes); + mm->add_instruction(make_op("where"), is_axes_empty, reduce_all_axes, reduce_input_axes); mm->add_return({where}); onnx_options options; diff --git a/test/onnx/reducel1_dyn_noaxes_test.onnx b/test/onnx/reducel1_dyn_noaxes_test.onnx new file mode 100644 index 0000000000000000000000000000000000000000..9f1a76a21de88eb1f7b83cba03fbfab5946d4b34 GIT binary patch literal 125 zcmd;J7m_GSO({)I%`uEmsmzPd%TKIGEsifqEiSQ&=2GNhtPoU5U|7J&gj;(QFGw>77aIqo5EBadd_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); - auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); + auto* mm = p.get_main_module(); + auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); + auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, axes); auto prog = optimize_onnx("reducesum_variable_axes_noop_set_test.onnx"); diff --git a/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp b/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp index e1932642312..03f7f9e3a83 100644 --- a/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp +++ b/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp @@ -29,21 +29,20 @@ std::vector reducesum_variable_dynamic_axes_test_base(migraphx::shape axes_shape, std::vector axes_data) { - using namespace migraphx; - onnx_options options; - const std::vector axes_dims{{0, 3}}; + migraphx::onnx_options options; + const std::vector axes_dims{{0, 3}}; options.map_dyn_input_dims["axes"] = axes_dims; - program p = parse_onnx("reducesum_variable_dynamic_axes_verify_test.onnx", options); - p.compile(make_target("ref")); + migraphx::program p = parse_onnx("reducesum_variable_dynamic_axes_verify_test.onnx", options); + p.compile(migraphx::make_target("ref")); - parameter_map pm; - shape x_shape{shape::float_type, {2, 2, 2}}; + migraphx::parameter_map pm; + migraphx::shape x_shape{migraphx::shape::float_type, {2, 2, 2}}; std::vector x(x_shape.elements()); std::iota(x.begin(), x.end(), 0); - pm["x"] = argument(x_shape, x.data()); + pm["x"] = migraphx::argument(x_shape, x.data()); std::vector axes{1}; - pm["axes"] = argument(axes_shape, axes_data.data()); + pm["axes"] = migraphx::argument(axes_shape, axes_data.data()); auto result = p.eval(pm).back(); std::vector result_vector; diff --git a/test/op_shape_test.cpp b/test/op_shape_test.cpp index c0bc3b67d59..948973e4b89 100644 --- a/test/op_shape_test.cpp +++ b/test/op_shape_test.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/test/ref/reduce_max.cpp b/test/ref/reduce_max.cpp index 6f79e2e11b0..bc353743b29 100644 --- a/test/ref/reduce_max.cpp +++ b/test/ref/reduce_max.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/test/ref/reduce_mean.cpp b/test/ref/reduce_mean.cpp index ff6fa7d3190..97806f2c999 100644 --- a/test/ref/reduce_mean.cpp +++ b/test/ref/reduce_mean.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/test/ref/reduce_min.cpp b/test/ref/reduce_min.cpp index 081019acfff..a007a9a341e 100644 --- a/test/ref/reduce_min.cpp +++ b/test/ref/reduce_min.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/test/ref/reduce_prod.cpp b/test/ref/reduce_prod.cpp index 909bb931a2f..ce034341b4f 100644 --- a/test/ref/reduce_prod.cpp +++ b/test/ref/reduce_prod.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/test/ref/reduce_sum.cpp b/test/ref/reduce_sum.cpp index 0f73d28109e..e48dbaf6c31 100644 --- a/test/ref/reduce_sum.cpp +++ b/test/ref/reduce_sum.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -259,3 +259,53 @@ TEST_CASE(reduce_sum_dynamic_variable_axis0) std::vector gold = {7, 9, 11, 13, 15}; EXPECT(migraphx::verify::verify_rms_range(results_vector, gold)); } + +TEST_CASE(reduce_sum_variable_dynamic_empty_axes) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + migraphx::shape s{migraphx::shape::float_type, {3, 2, 2}}; + std::vector input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + auto input = migraphx::literal{s, input_data}; + auto l0 = mm->add_literal(input); + const std::vector axes_dynamic_dims{{0, 3}}; + migraphx::shape axes_dynamic_shape{migraphx::shape::int64_type, axes_dynamic_dims}; + auto axes = mm->add_parameter("axes", axes_dynamic_shape); + + migraphx::parameter_map pm; + migraphx::shape axes_shape{migraphx::shape::int64_type, {0}}; + std::vector axes_data; + pm["axes"] = migraphx::argument(axes_shape, axes_data.data()); + + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {}}}), l0, axes); + p.compile(migraphx::make_target("ref")); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + EXPECT(results_vector == input_data); +} + +TEST_CASE(reduce_sum_variable_empty_axes) +{ + migraphx::program p; + auto* mm = p.get_main_module(); + migraphx::shape s{migraphx::shape::float_type, {3, 2, 2}}; + std::vector input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + auto input = migraphx::literal{s, input_data}; + auto l0 = mm->add_literal(input); + migraphx::shape axes_shape{migraphx::shape::int64_type, {0}}; + auto axes = mm->add_parameter("axes", axes_shape); + + migraphx::parameter_map pm; + std::vector axes_data; + pm["axes"] = migraphx::argument(axes_shape, axes_data.data()); + + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {}}}), l0, axes); + p.compile(migraphx::make_target("ref")); + auto result = p.eval(pm).back(); + std::vector results_vector; + result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); + + EXPECT(results_vector == input_data); +} From 5f7b702f88e13dc97ae8be108c11031046b5e1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 7 Feb 2024 13:57:17 +0000 Subject: [PATCH 20/25] Fix formatting, cppcheck, and tidy issues --- src/include/migraphx/op/reduce_op.hpp | 7 ++-- test/onnx/gen_onnx.py | 5 ++- .../parse/reducesum_variable_axes_test.cpp | 10 +++--- .../reducesum_variable_dynamic_axes_test.cpp | 32 +++++++++---------- .../reducesum_variable_empty_axes_test.cpp | 15 ++++----- .../reducesum_variable_axes_noop_test.cpp | 10 +++--- 6 files changed, 37 insertions(+), 42 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index f05c8f8e26a..1b7d4bc5a45 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -224,15 +224,12 @@ struct reduce_op : op_name argument compute(const dyn_output& dyn_out, std::vector args) const { auto&& data_arg = args[0]; + // cppcheck-suppress knownConditionTrueFalse if(not axes.empty()) - { return reduce(dyn_out.computed_shape, axes, data_arg); - } - if(axes.empty() and args[1].empty()) - { + if(args[1].empty()) return args[0]; - } std::vector reduce_axes; args[1].visit([&](auto&& s) { reduce_axes.assign(s.begin(), s.end()); }); diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index 8d41d4b9d2d..8770e42de09 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -7254,7 +7254,10 @@ def recip_test(): return ([node], [x], [y]) -def reduceop_variable_axes_test(op_name, axes_len=1, keepdims=1, noop_with_empty_axes=0): +def reduceop_variable_axes_test(op_name, + axes_len=1, + keepdims=1, + noop_with_empty_axes=0): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [3, 4, 5, 6]) axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [axes_len]) y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [3, 4, 1, 6]) diff --git a/test/onnx/parse/reducesum_variable_axes_test.cpp b/test/onnx/parse/reducesum_variable_axes_test.cpp index ef8c0fdec69..af2dfcf9c93 100644 --- a/test/onnx/parse/reducesum_variable_axes_test.cpp +++ b/test/onnx/parse/reducesum_variable_axes_test.cpp @@ -25,13 +25,11 @@ TEST_CASE(reducesum_variable_axes_test) { - using namespace migraphx; - - program p; + migraphx::program p; auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); - auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, axes); + auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + auto axes = mm->add_parameter("axes", migraphx::shape{migraphx::shape::int64_type, {1}}); + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {}}}), x, axes); auto prog = optimize_onnx("reducesum_variable_axes_test.onnx"); EXPECT(p == prog); diff --git a/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp b/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp index b101ee7bb59..63c5200ff71 100644 --- a/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp +++ b/test/onnx/parse/reducesum_variable_dynamic_axes_test.cpp @@ -25,30 +25,30 @@ TEST_CASE(reducesum_variable_dynamic_axes_test) { - using namespace migraphx; - - program p; + migraphx::program p; auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); - const std::vector axes_dims{{0, 3}}; - auto axes = mm->add_parameter("axes", shape{shape::int64_type, axes_dims}); + auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + const std::vector axes_dims{{0, 3}}; + auto axes = mm->add_parameter("axes", migraphx::shape{migraphx::shape::int64_type, axes_dims}); - auto reduce_input_axes = mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, axes); + auto reduce_input_axes = + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {}}}), x, axes); std::vector all_axes(x->get_shape().ndim()); std::iota(all_axes.begin(), all_axes.end(), 0); - auto all_axes_lit = - mm->add_literal(literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); + auto all_axes_lit = mm->add_literal(migraphx::literal{ + migraphx::shape{migraphx::shape::type_t::int64_type, {all_axes.size()}}, all_axes}); auto reduce_all_axes = - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, all_axes_lit); + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {}}}), x, all_axes_lit); - auto zero_lit = mm->add_literal(literal{shape{shape::int64_type}, {0u}}); - auto axes_size = mm->add_instruction(make_op("dimensions_of", {{"end", 1}}), axes); - auto is_axes_empty = mm->add_instruction(make_op("equal"), axes_size, zero_lit); - auto where = - mm->add_instruction(make_op("where"), is_axes_empty, reduce_all_axes, reduce_input_axes); + auto zero_lit = + mm->add_literal(migraphx::literal{migraphx::shape{migraphx::shape::int64_type}, {0u}}); + auto axes_size = mm->add_instruction(migraphx::make_op("dimensions_of", {{"end", 1}}), axes); + auto is_axes_empty = mm->add_instruction(migraphx::make_op("equal"), axes_size, zero_lit); + auto where = mm->add_instruction( + migraphx::make_op("where"), is_axes_empty, reduce_all_axes, reduce_input_axes); mm->add_return({where}); - onnx_options options; + migraphx::onnx_options options; options.map_dyn_input_dims["axes"] = axes->get_shape().dyn_dims(); auto prog = parse_onnx("reducesum_variable_dynamic_axes_test.onnx", options); EXPECT(p == prog); diff --git a/test/onnx/parse/reducesum_variable_empty_axes_test.cpp b/test/onnx/parse/reducesum_variable_empty_axes_test.cpp index a1e72537dc8..cb660001b97 100644 --- a/test/onnx/parse/reducesum_variable_empty_axes_test.cpp +++ b/test/onnx/parse/reducesum_variable_empty_axes_test.cpp @@ -25,21 +25,20 @@ TEST_CASE(reducesum_variable_empty_axes_test) { - using namespace migraphx; - program p; + migraphx::program p; auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); - auto axes = mm->add_parameter("axes", shape{shape::int64_type, {0}}); + auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + auto axes = mm->add_parameter("axes", migraphx::shape{migraphx::shape::int64_type, {0}}); std::vector all_axes(x->get_shape().ndim()); std::iota(all_axes.begin(), all_axes.end(), 0); - auto all_axes_lit = - mm->add_literal(literal{shape{shape::type_t::int64_type, {all_axes.size()}}, all_axes}); + auto all_axes_lit = mm->add_literal(migraphx::literal{ + migraphx::shape{migraphx::shape::int64_type, {all_axes.size()}}, all_axes}); auto reduce_all_axes = - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, all_axes_lit); + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {}}}), x, all_axes_lit); mm->add_return({reduce_all_axes}); - onnx_options options; + migraphx::onnx_options options; options.map_input_dims["axes"] = axes->get_shape().lens(); auto prog = parse_onnx("reducesum_variable_axes_test.onnx", options); EXPECT(p == prog); diff --git a/test/onnx/reducesum_variable_axes_noop_test.cpp b/test/onnx/reducesum_variable_axes_noop_test.cpp index 6c06d278d61..dff6d61136f 100644 --- a/test/onnx/reducesum_variable_axes_noop_test.cpp +++ b/test/onnx/reducesum_variable_axes_noop_test.cpp @@ -25,13 +25,11 @@ TEST_CASE(reducesum_variable_axes_noop_set_test) { - using namespace migraphx; - - program p; + migraphx::program p; auto* mm = p.get_main_module(); - auto x = mm->add_parameter("x", shape{shape::float_type, {3, 4, 5, 6}}); - auto axes = mm->add_parameter("axes", shape{shape::int64_type, {1}}); - mm->add_instruction(make_op("reduce_sum", {{"axes", {}}}), x, axes); + auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + auto axes = mm->add_parameter("axes", migraphx::shape{migraphx::shape::int64_type, {1}}); + mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {}}}), x, axes); auto prog = optimize_onnx("reducesum_variable_axes_noop_set_test.onnx"); EXPECT(p == prog); From 2e6e5e85670888041bab269c74f375e67d27fe13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Tue, 27 Feb 2024 23:09:22 +0000 Subject: [PATCH 21/25] Remove superfluous onnx test files, and add additional test cases for variable dynamic axes --- src/include/migraphx/op/reduce_op.hpp | 2 +- test/onnx/gen_onnx.py | 13 +++++ ...reduce_log_sum_exp_variable_axes_test.onnx | 21 ------- .../reduce_log_sum_variable_axes_test.onnx | 21 ------- test/onnx/reducel2_variable_axes_test.onnx | 21 ------- test/onnx/reducemax_variable_axes_test.onnx | 21 ------- test/onnx/reducemean_variable_axes_test.onnx | 22 -------- test/onnx/reducemin_variable_axes_test.onnx | 21 ------- test/onnx/reduceprod_variable_axes_test.onnx | 22 -------- .../reducesum_square_variable_axes_test.onnx | 21 ------- ...ble_dynamic_axes_noop_set_verify_test.onnx | Bin 0 -> 229 bytes .../reducesum_variable_dynamic_axes_test.cpp | 52 ++++++++++++++---- 12 files changed, 56 insertions(+), 181 deletions(-) delete mode 100644 test/onnx/reduce_log_sum_exp_variable_axes_test.onnx delete mode 100644 test/onnx/reduce_log_sum_variable_axes_test.onnx delete mode 100644 test/onnx/reducel2_variable_axes_test.onnx delete mode 100644 test/onnx/reducemax_variable_axes_test.onnx delete mode 100644 test/onnx/reducemean_variable_axes_test.onnx delete mode 100644 test/onnx/reducemin_variable_axes_test.onnx delete mode 100644 test/onnx/reduceprod_variable_axes_test.onnx delete mode 100644 test/onnx/reducesum_square_variable_axes_test.onnx create mode 100644 test/onnx/reducesum_variable_dynamic_axes_noop_set_verify_test.onnx diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 1b7d4bc5a45..85a292a84dc 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -228,7 +228,7 @@ struct reduce_op : op_name if(not axes.empty()) return reduce(dyn_out.computed_shape, axes, data_arg); - if(args[1].empty()) + if(args[1].get_shape().elements() == 0) return args[0]; std::vector reduce_axes; diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index 4f732ba7664..e858e393844 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -7622,6 +7622,19 @@ def reducesum_variable_dynamic_axes_verify_test(): return ([node], [x, axes], [y]) +@onnx_test() +def reducesum_variable_dynamic_axes_noop_set_verify_test(): + x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [2, 2, 2]) + axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [None]) + y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [None]) + + node = onnx.helper.make_node('ReduceSum', + inputs=['x', 'axes'], + outputs=['y'], + noop_with_empty_axes=1) + + return ([node], [x, axes], [y]) + @onnx_test() def reducesum_square_test(): diff --git a/test/onnx/reduce_log_sum_exp_variable_axes_test.onnx b/test/onnx/reduce_log_sum_exp_variable_axes_test.onnx deleted file mode 100644 index fac02d3bfba..00000000000 --- a/test/onnx/reduce_log_sum_exp_variable_axes_test.onnx +++ /dev/null @@ -1,21 +0,0 @@ - %reduce_log_sum_exp_variable_axes_test:₯ -. -x -axesy"ReduceLogSumExp* -keepdims %reduce_log_sum_exp_variable_axes_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reduce_log_sum_variable_axes_test.onnx b/test/onnx/reduce_log_sum_variable_axes_test.onnx deleted file mode 100644 index 88587aefef6..00000000000 --- a/test/onnx/reduce_log_sum_variable_axes_test.onnx +++ /dev/null @@ -1,21 +0,0 @@ - !reduce_log_sum_variable_axes_test:ž -+ -x -axesy" ReduceLogSum* -keepdims !reduce_log_sum_variable_axes_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reducel2_variable_axes_test.onnx b/test/onnx/reducel2_variable_axes_test.onnx deleted file mode 100644 index b4e81db6d11..00000000000 --- a/test/onnx/reducel2_variable_axes_test.onnx +++ /dev/null @@ -1,21 +0,0 @@ - reducel2_variable_axes_test:” -' -x -axesy"ReduceL2* -keepdims reducel2_variable_axes_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reducemax_variable_axes_test.onnx b/test/onnx/reducemax_variable_axes_test.onnx deleted file mode 100644 index 030160ca1ca..00000000000 --- a/test/onnx/reducemax_variable_axes_test.onnx +++ /dev/null @@ -1,21 +0,0 @@ - reducemax_variable_axes_test:– -( -x -axesy" ReduceMax* -keepdims reducemax_variable_axes_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reducemean_variable_axes_test.onnx b/test/onnx/reducemean_variable_axes_test.onnx deleted file mode 100644 index 77002df2d13..00000000000 --- a/test/onnx/reducemean_variable_axes_test.onnx +++ /dev/null @@ -1,22 +0,0 @@ - reducemean_variable_axes_test:˜ -) -x -axesy" -ReduceMean* -keepdims reducemean_variable_axes_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reducemin_variable_axes_test.onnx b/test/onnx/reducemin_variable_axes_test.onnx deleted file mode 100644 index 58aa4f094e2..00000000000 --- a/test/onnx/reducemin_variable_axes_test.onnx +++ /dev/null @@ -1,21 +0,0 @@ - reducemin_variable_axes_test:– -( -x -axesy" ReduceMin* -keepdims reducemin_variable_axes_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reduceprod_variable_axes_test.onnx b/test/onnx/reduceprod_variable_axes_test.onnx deleted file mode 100644 index f7fc5ef97a6..00000000000 --- a/test/onnx/reduceprod_variable_axes_test.onnx +++ /dev/null @@ -1,22 +0,0 @@ - reduceprod_variable_axes_test:˜ -) -x -axesy" -ReduceProd* -keepdims reduceprod_variable_axes_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reducesum_square_variable_axes_test.onnx b/test/onnx/reducesum_square_variable_axes_test.onnx deleted file mode 100644 index 4b2a93bbab0..00000000000 --- a/test/onnx/reducesum_square_variable_axes_test.onnx +++ /dev/null @@ -1,21 +0,0 @@ - #reducesum_square_variable_axes_test:£ -. -x -axesy"ReduceSumSquare* -keepdims #reducesum_square_variable_axes_testZ -x - - - - -Z -axes - - -b -y - - - - -B \ No newline at end of file diff --git a/test/onnx/reducesum_variable_dynamic_axes_noop_set_verify_test.onnx b/test/onnx/reducesum_variable_dynamic_axes_noop_set_verify_test.onnx new file mode 100644 index 0000000000000000000000000000000000000000..6304cc83ca0e0704dbcc8783f5d85d762620a291 GIT binary patch literal 229 zcmdi#D#aO|`0#YKxSgFJr1U4qPG*?TSO9ZT^JhLPtJ~g+Xq!Mh91mglm zCi1L{5(nBPB*Z1a!6?MT#l*n`!%+fI7jST~aj*+9aWN$Eaxqp4fw+tyt`n1hFaQ+M BLfZfU literal 0 HcmV?d00001 diff --git a/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp b/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp index 03f7f9e3a83..aceb49cd180 100644 --- a/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp +++ b/test/onnx/verify/reducesum_variable_dynamic_axes_test.cpp @@ -26,13 +26,16 @@ #include #include -std::vector reducesum_variable_dynamic_axes_test_base(migraphx::shape axes_shape, - std::vector axes_data) +auto reducesum_variable_dynamic_axes_test_base(migraphx::shape axes_shape, + std::vector axes_data, + const std::string& file) { + std::pair, migraphx::shape> ret; + migraphx::onnx_options options; const std::vector axes_dims{{0, 3}}; options.map_dyn_input_dims["axes"] = axes_dims; - migraphx::program p = parse_onnx("reducesum_variable_dynamic_axes_verify_test.onnx", options); + migraphx::program p = parse_onnx(file, options); p.compile(migraphx::make_target("ref")); migraphx::parameter_map pm; @@ -45,23 +48,52 @@ std::vector reducesum_variable_dynamic_axes_test_base(migraphx::shape axe pm["axes"] = migraphx::argument(axes_shape, axes_data.data()); auto result = p.eval(pm).back(); - std::vector result_vector; - result.visit([&](auto output) { result_vector.assign(output.begin(), output.end()); }); - return result_vector; + ret.second = result.get_shape(); + result.visit([&](auto output) { ret.first.assign(output.begin(), output.end()); }); + return ret; } TEST_CASE(reducesum_variable_dynamic_axes_test) { - auto result = reducesum_variable_dynamic_axes_test_base({migraphx::shape::int64_type, {1}}, - std::vector{1}); + auto [result, shape] = reducesum_variable_dynamic_axes_test_base( + {migraphx::shape::int64_type, {1}}, + std::vector{1}, + "reducesum_variable_dynamic_axes_verify_test.onnx"); std::vector gold{2, 4, 10, 12}; + EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {2, 1, 2}}); EXPECT(result == gold); } TEST_CASE(reducesum_variable_dynamic_axes_empty_test) { - auto result = reducesum_variable_dynamic_axes_test_base({migraphx::shape::int64_type, {0}}, - std::vector{}); + auto [result, shape] = reducesum_variable_dynamic_axes_test_base( + {migraphx::shape::int64_type, {0}}, + std::vector{}, + "reducesum_variable_dynamic_axes_verify_test.onnx"); std::vector gold{28}; + EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {1, 1, 1}}); + EXPECT(result == gold); +} + +TEST_CASE(reducesum_variable_dynamic_axes_noop_set_test) +{ + auto [result, shape] = reducesum_variable_dynamic_axes_test_base( + {migraphx::shape::int64_type, {1}}, + std::vector{1}, + "reducesum_variable_dynamic_axes_noop_set_verify_test.onnx"); + std::vector gold{2, 4, 10, 12}; + EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {2, 1, 2}}); + EXPECT(result == gold); +} + +TEST_CASE(reducesum_variable_dynamic_axes_empty_noop_set_test) +{ + auto [result, shape] = reducesum_variable_dynamic_axes_test_base( + {migraphx::shape::int64_type, {0}}, + std::vector{}, + "reducesum_variable_dynamic_axes_noop_set_verify_test.onnx"); + std::vector gold(8); + std::iota(gold.begin(), gold.end(), 0); + EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {2, 2, 2}}); EXPECT(result == gold); } From c350c5fb9cb69ee508e2884efaff569ed4f808d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 28 Feb 2024 10:47:15 +0000 Subject: [PATCH 22/25] Add some documentation for reduce_op, and implement additional onnx_verify test cases --- src/include/migraphx/op/reduce_op.hpp | 22 +++- .../reducesum_variable_axes_noop_test.cpp | 4 +- .../verify/reducesum_variable_axes_test.cpp | 105 ++++++++++++++++++ 3 files changed, 127 insertions(+), 4 deletions(-) rename test/onnx/{ => parse}/reducesum_variable_axes_noop_test.cpp (92%) create mode 100644 test/onnx/verify/reducesum_variable_axes_test.cpp diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index 85a292a84dc..fd7dad30450 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -106,6 +106,14 @@ struct reduce_op : op_name return original_shape.with_lens(lens); } + // Compute the output shape for cases when the input tensor has a dynamic shape. + // + // If the axes are passed as an attribute, or a constant input, we can precisely + // determine which axes need to be collapsed even during parsing. + // + // If the axes are passed as a variable input(indicated by an empty axes attribute), we cannot + // determine which axes must be collapsed until we see the actual input values, so we must treat + // each axis as potentially collapsable and set its minimum dimension to 1. shape compute_dynamic_shape(const std::vector& inputs) const { const auto& data_shape = inputs[0]; @@ -128,6 +136,16 @@ struct reduce_op : op_name return {data_shape.type(), dims}; } + // Compute the output shape for cases when the input tensor has a static shape. + // Depending on how axes is passed to the operator the output shape can be either dynamic or + // static. + // + // If the axes are passed as an attribute, or a constant input, we can precisely + // determine which axes need to be collapsed even during parsing. + // + // If the axes are passed as a variable input(indicated by an empty axes attribute), we cannot + // determine which axes must be collapsed until we see the actual input values, so we must treat + // each axis as potentially collapsable, producing a dynamic output shape. shape compute_static_shape(const std::vector& inputs) const { const auto& data_shape = inputs[0]; @@ -135,8 +153,8 @@ struct reduce_op : op_name { std::vector dims(data_shape.ndim()); auto lens = data_shape.lens(); - std::transform(lens.begin(), lens.end(), dims.begin(), [](auto l) { - return shape::dynamic_dimension{1, l}; + std::transform(lens.begin(), lens.end(), dims.begin(), [](auto len) { + return shape::dynamic_dimension{1, len}; }); return {data_shape.type(), std::move(dims)}; diff --git a/test/onnx/reducesum_variable_axes_noop_test.cpp b/test/onnx/parse/reducesum_variable_axes_noop_test.cpp similarity index 92% rename from test/onnx/reducesum_variable_axes_noop_test.cpp rename to test/onnx/parse/reducesum_variable_axes_noop_test.cpp index dff6d61136f..b6fa81f03b7 100644 --- a/test/onnx/reducesum_variable_axes_noop_test.cpp +++ b/test/onnx/parse/reducesum_variable_axes_noop_test.cpp @@ -23,7 +23,7 @@ */ #include -TEST_CASE(reducesum_variable_axes_noop_set_test) +TEST_CASE(reducesum_variable_axes_noop_test) { migraphx::program p; auto* mm = p.get_main_module(); @@ -31,6 +31,6 @@ TEST_CASE(reducesum_variable_axes_noop_set_test) auto axes = mm->add_parameter("axes", migraphx::shape{migraphx::shape::int64_type, {1}}); mm->add_instruction(migraphx::make_op("reduce_sum", {{"axes", {}}}), x, axes); - auto prog = optimize_onnx("reducesum_variable_axes_noop_set_test.onnx"); + auto prog = optimize_onnx("reducesum_variable_axes_noop_test.onnx"); EXPECT(p == prog); } diff --git a/test/onnx/verify/reducesum_variable_axes_test.cpp b/test/onnx/verify/reducesum_variable_axes_test.cpp new file mode 100644 index 00000000000..afde95ef09a --- /dev/null +++ b/test/onnx/verify/reducesum_variable_axes_test.cpp @@ -0,0 +1,105 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2024 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +auto reducesum_variable_axes_test_base(const std::string& file, size_t axes_size) +{ + std::pair, migraphx::shape> ret; + + migraphx::onnx_options options; + options.map_input_dims["axes"] = std::vector{axes_size}; + migraphx::program p = migraphx::parse_onnx(file, options); + p.compile(migraphx::make_target("ref")); + + migraphx::parameter_map pm; + migraphx::shape x_shape{migraphx::shape::float_type, {3, 4, 5, 6}}; + std::vector x(x_shape.elements()); + std::iota(x.begin(), x.end(), 0); + pm["x"] = migraphx::argument(x_shape, x.data()); + auto axes_data = axes_size == 0 ? std::vector{} : std::vector{2}; + pm["axes"] = migraphx::argument(migraphx::shape{migraphx::shape::int64_type, {axes_size}}, + axes_data.data()); + + auto result = p.eval(pm).back(); + std::vector result_vector; + result.visit([&](auto output) { ret.first.assign(output.begin(), output.end()); }); + ret.second = result.get_shape(); + + return ret; +} + +TEST_CASE(bla) +{ + auto [result_vector, shape] = + reducesum_variable_axes_test_base("reducesum_variable_axes_test.onnx", 1); + std::vector gold{60, 65, 70, 75, 80, 85, 210, 215, 220, 225, 230, 235, + 360, 365, 370, 375, 380, 385, 510, 515, 520, 525, 530, 535, + 660, 665, 670, 675, 680, 685, 810, 815, 820, 825, 830, 835, + 960, 965, 970, 975, 980, 985, 1110, 1115, 1120, 1125, 1130, 1135, + 1260, 1265, 1270, 1275, 1280, 1285, 1410, 1415, 1420, 1425, 1430, 1435, + 1560, 1565, 1570, 1575, 1580, 1585, 1710, 1715, 1720, 1725, 1730, 1735}; + + EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {3, 4, 1, 6}}); + EXPECT(result_vector == gold); +} + +TEST_CASE(bla2) +{ + auto [result_vector, shape] = + reducesum_variable_axes_test_base("reducesum_variable_axes_test.onnx", 0); + std::vector gold{64620}; + + EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {1, 1, 1, 1}}); + EXPECT(result_vector == gold); +} + +TEST_CASE(bla3) +{ + auto [result_vector, shape] = + reducesum_variable_axes_test_base("reducesum_variable_axes_noop_test.onnx", 1); + std::vector gold{60, 65, 70, 75, 80, 85, 210, 215, 220, 225, 230, 235, + 360, 365, 370, 375, 380, 385, 510, 515, 520, 525, 530, 535, + 660, 665, 670, 675, 680, 685, 810, 815, 820, 825, 830, 835, + 960, 965, 970, 975, 980, 985, 1110, 1115, 1120, 1125, 1130, 1135, + 1260, 1265, 1270, 1275, 1280, 1285, 1410, 1415, 1420, 1425, 1430, 1435, + 1560, 1565, 1570, 1575, 1580, 1585, 1710, 1715, 1720, 1725, 1730, 1735}; + + EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {3, 4, 1, 6}}); + EXPECT(result_vector == gold); +} + +TEST_CASE(bla4) +{ + auto [result_vector, shape] = + reducesum_variable_axes_test_base("reducesum_variable_axes_noop_test.onnx", 0); + std::vector gold(3 * 4 * 5 * 6); + std::iota(gold.begin(), gold.end(), 0); + + EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); + EXPECT(result_vector == gold); +} + From 13364ec90745546513a1f6736b8fb41d4cb3130f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 28 Feb 2024 11:55:24 +0000 Subject: [PATCH 23/25] Fix formatting issue in gen_onnx.py --- test/onnx/gen_onnx.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/onnx/gen_onnx.py b/test/onnx/gen_onnx.py index 85e316c7513..a0c5c3e7640 100644 --- a/test/onnx/gen_onnx.py +++ b/test/onnx/gen_onnx.py @@ -7629,6 +7629,7 @@ def reducesum_variable_dynamic_axes_verify_test(): return ([node], [x, axes], [y]) + @onnx_test() def reducesum_variable_dynamic_axes_noop_set_verify_test(): x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [2, 2, 2]) From d92a66436ebb9b9f7ad645fab980a8be2e09446b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Wed, 28 Feb 2024 13:14:11 +0000 Subject: [PATCH 24/25] Fixed formatting issue --- test/onnx/verify/reducesum_variable_axes_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/onnx/verify/reducesum_variable_axes_test.cpp b/test/onnx/verify/reducesum_variable_axes_test.cpp index afde95ef09a..e747c4db702 100644 --- a/test/onnx/verify/reducesum_variable_axes_test.cpp +++ b/test/onnx/verify/reducesum_variable_axes_test.cpp @@ -102,4 +102,3 @@ TEST_CASE(bla4) EXPECT(shape == migraphx::shape{migraphx::shape::float_type, {3, 4, 5, 6}}); EXPECT(result_vector == gold); } - From 766ecfedc559a3f8cff27d9e693583a084aec521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Musi=C4=87?= Date: Tue, 5 Mar 2024 14:25:31 +0000 Subject: [PATCH 25/25] Update code comments --- src/include/migraphx/op/reduce_op.hpp | 6 ------ src/onnx/parse_reduce_op.cpp | 2 ++ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/include/migraphx/op/reduce_op.hpp b/src/include/migraphx/op/reduce_op.hpp index fd7dad30450..c1fc5e56731 100644 --- a/src/include/migraphx/op/reduce_op.hpp +++ b/src/include/migraphx/op/reduce_op.hpp @@ -108,9 +108,6 @@ struct reduce_op : op_name // Compute the output shape for cases when the input tensor has a dynamic shape. // - // If the axes are passed as an attribute, or a constant input, we can precisely - // determine which axes need to be collapsed even during parsing. - // // If the axes are passed as a variable input(indicated by an empty axes attribute), we cannot // determine which axes must be collapsed until we see the actual input values, so we must treat // each axis as potentially collapsable and set its minimum dimension to 1. @@ -140,9 +137,6 @@ struct reduce_op : op_name // Depending on how axes is passed to the operator the output shape can be either dynamic or // static. // - // If the axes are passed as an attribute, or a constant input, we can precisely - // determine which axes need to be collapsed even during parsing. - // // If the axes are passed as a variable input(indicated by an empty axes attribute), we cannot // determine which axes must be collapsed until we see the actual input values, so we must treat // each axis as potentially collapsable, producing a dynamic output shape. diff --git a/src/onnx/parse_reduce_op.cpp b/src/onnx/parse_reduce_op.cpp index e3871004653..9d69c1b15f4 100644 --- a/src/onnx/parse_reduce_op.cpp +++ b/src/onnx/parse_reduce_op.cpp @@ -72,6 +72,8 @@ struct reduce_parser : op_parser MIGRAPHX_THROW("Keepdims not supported with runtime provided axes"); // Empty axes attribute indicates to the operator to look for axes in the inputs + // If the input axes are empty, the default behavior of reduce_op is to be an + // identity operator auto reduce_op = make_op(op_name, {{"axes", {}}}); if(noop_with_empty_axes != 0)