[GPU] Reduce to use ngraph shape infer at calc_output_layouts (#13032)

This commit is contained in:
Kelvin Choi
2022-09-26 14:51:21 +09:00
committed by GitHub
parent 12f1e95c3d
commit 766c289e15
3 changed files with 233 additions and 0 deletions

View File

@@ -27,6 +27,8 @@ class typed_primitive_inst<reduce> : public typed_primitive_inst_base<reduce> {
using parent = typed_primitive_inst_base<reduce>;
public:
template<typename ShapeType>
static std::vector<layout> calc_output_layouts(reduce_node const& node, const kernel_impl_params& impl_param);
static layout calc_output_layout(reduce_node const& node, kernel_impl_params const& impl_param);
static std::string to_string(reduce_node const& node);

View File

@@ -11,6 +11,8 @@
#include <vector>
#include <string>
#include "reduce_shape_inference.hpp"
namespace cldnn {
primitive_type_id reduce::type_id() {
static primitive_type_base<reduce> instance;
@@ -95,6 +97,119 @@ layout reduce_inst::calc_output_layout(reduce_node const& node, kernel_impl_para
return layout{output_type, input_format, tensor(batch(in_dims[0]), feature(in_dims[1]), spatial(in_dims[2], in_dims[3]))};
}
template<typename ShapeType>
std::vector<layout> reduce_inst::calc_output_layouts(reduce_node const& /*node*/, kernel_impl_params const& impl_param) {
auto desc = impl_param.typed_desc<reduce>();
auto input0_layout = impl_param.get_input_layout(0);
// get 'output_shapes' by shape_infer of ngraph
std::vector<ShapeType> input_shapes = {
input0_layout.get<ShapeType>(),
ShapeType{0}
};
std::vector<ShapeType> output_shapes = {ShapeType()};
auto axes = desc->axes;
auto axes_tensor = std::make_shared<ngraph::runtime::HostTensor>(ov::element::i64, ov::Shape{axes.size()}, axes.data());
std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>> const_data = {{1, axes_tensor}};
// shape infer by mode
auto mode = desc->mode;
auto keep_dims = desc->keep_dims;
switch (mode) {
case reduce_mode::max:
{
ov::op::v1::ReduceMax op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::min:
{
ov::op::v1::ReduceMin op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::mean:
{
ov::op::v1::ReduceMean op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::prod:
{
ov::op::v1::ReduceProd op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::sum:
{
ov::op::v1::ReduceSum op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::logical_and:
{
ov::op::v1::ReduceLogicalAnd op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::logical_or:
{
ov::op::v1::ReduceLogicalOr op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::l1:
{
ov::op::v4::ReduceL1 op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::l2:
{
ov::op::v4::ReduceL2 op;
op.set_keep_dims(keep_dims);
shape_infer(&op, input_shapes, output_shapes, const_data);
break;
}
case reduce_mode::sum_square:
// not implemented
case reduce_mode::log_sum:
// not implemented
case reduce_mode::log_sum_exp:
// not implemented
default:
OPENVINO_ASSERT(false, "Not supported reduce mode");
}
auto input_type = input0_layout.data_type;
auto output_type = input_type;
std::vector<reduce_mode> reduce_bool_modes = {reduce_mode::logical_and, reduce_mode::logical_or};
if (std::find(reduce_bool_modes.begin(), reduce_bool_modes.end(), mode) != reduce_bool_modes.end())
output_type = data_types::i8;
else if (input_type == data_types::i8 || input_type == data_types::u8)
output_type = data_types::f32;
output_type = desc->output_data_type.value_or(output_type);
if (impl_param.has_fused_primitives())
output_type = impl_param.get_fused_output_layout().data_type;
auto output_format = format::adjust_to_rank(input0_layout.format, output_shapes[0].size());
return { layout{output_shapes[0], output_type, output_format} };
}
std::string reduce_inst::to_string(reduce_node const& node) {
auto desc = node.get_primitive();
auto node_info = node.desc_to_json();

View File

@@ -0,0 +1,116 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "test_utils.h"
#include <intel_gpu/primitives/input_layout.hpp>
#include <intel_gpu/primitives/reduce.hpp>
#include <intel_gpu/primitives/data.hpp>
#include "reduce_inst.h"
#include "program_wrapper.h"
#include <cmath>
#include <algorithm>
using namespace cldnn;
using namespace ::tests;
namespace shape_infer_tests {
struct reduce_test_params {
layout input;
reduce_mode mode;
std::vector<int64_t> axes;
bool keep_dims;
layout expected_layout;
};
class reduce_test : public testing::TestWithParam<reduce_test_params> { };
TEST_P(reduce_test, shape_infer) {
auto p = GetParam();
auto& engine = get_test_engine();
auto input_prim = std::make_shared<input_layout>("input", p.input);
auto reduce_prim = std::make_shared<reduce>("output", "input", p.mode, p.axes, p.keep_dims);
cldnn::program prog(engine);
auto& input_node = prog.get_or_create(input_prim);
auto& reduce_node = prog.get_or_create(reduce_prim);
program_wrapper::add_connection(prog, input_node, reduce_node);
auto res = reduce_inst::calc_output_layouts<ov::PartialShape>(reduce_node, *reduce_node.get_kernel_impl_params());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], p.expected_layout);
}
INSTANTIATE_TEST_SUITE_P(smoke, reduce_test,
testing::ValuesIn(std::vector<reduce_test_params>{
{
layout{ov::PartialShape{1, 1, 1, 1}, data_types::f32, format::bfyx},
reduce_mode::max, {1}, false,
layout{ov::PartialShape{1}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{1, 1, 1, 1}, data_types::f32, format::bfyx},
reduce_mode::min, {1}, true,
layout{ov::PartialShape{1, 1, 1, 1}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10, 24}, data_types::f32, format::bfyx},
reduce_mode::mean, {1}, false,
layout{ov::PartialShape{6, 10, 24}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10, 24}, data_types::f32, format::bfyx},
reduce_mode::prod, {1}, true,
layout{ov::PartialShape{6, 1, 10, 24}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{6, 12}, data_types::f32, format::bfyx},
reduce_mode::sum, {1}, false,
layout{ov::PartialShape{6}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10}, data_types::f32, format::bfyx},
reduce_mode::logical_and, {1}, false,
layout{ov::PartialShape{6, 10}, data_types::i8, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10}, data_types::f32, format::bfyx},
reduce_mode::logical_or, {1}, true,
layout{ov::PartialShape{6, 1, 10}, data_types::i8, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10, 24}, data_types::f32, format::bfyx},
reduce_mode::l1, {2, 3}, false,
layout{ov::PartialShape{6, 12}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10, 24}, data_types::f32, format::bfyx},
reduce_mode::l2, {2, 3}, true,
layout{ov::PartialShape{6, 12, 1, 1}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10, 24}, data_types::f32, format::bfyx},
reduce_mode::max, {-2}, false,
layout{ov::PartialShape{6, 12, 24}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10, 24, 3}, data_types::f32, format::bfzyx},
reduce_mode::min, {2, 3}, false,
layout{ov::PartialShape{6, 12, 3}, data_types::f32, format::bfyx}
},
{
layout{ov::PartialShape{6, 12, 10, 24, 3, 5}, data_types::f32, format::bfwzyx},
reduce_mode::sum, {2, 3}, false,
layout{ov::PartialShape{6, 12, 3, 5}, data_types::f32, format::bfyx}
},
}));
} // shape_infer_tests