[GPU] Implement bias on internal FC op (#23317)

Added bias semantics support for internal FC op

### Details:
 - Added bias semantics support for internal FC op
This commit is contained in:
Damian Kurek 2024-03-12 12:16:41 +01:00 committed by GitHub
parent 6c55b70455
commit ebde6c817b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 128 additions and 65 deletions

View File

@ -19,6 +19,7 @@ public:
FullyConnected(const ov::Output<Node>& A,
const ov::Output<Node>& B,
const ov::Output<Node>& bias,
const ov::element::Type output_type = ov::element::undefined);
bool visit_attributes(ov::AttributeVisitor &visitor) override;

View File

@ -18,12 +18,14 @@ public:
FullyConnectedCompressed(const ov::Output<Node> &A,
const ov::Output<Node> &B,
const ov::Output<Node> &bias,
const ov::Output<Node> &decompression_scale,
const ov::Output<Node> &decompression_zero_point,
const ov::element::Type output_type = ov::element::undefined);
FullyConnectedCompressed(const ov::Output<Node> &A,
const ov::Output<Node> &B,
const ov::Output<Node> &bias,
const ov::Output<Node> &decompression_scale,
const ov::element::Type output_type = ov::element::undefined);

View File

@ -26,14 +26,15 @@ namespace ov {
namespace intel_gpu {
static void CreateFullyConnectedCompressedOp(ProgramBuilder& p, const std::shared_ptr<op::FullyConnectedCompressed>& op) {
validate_inputs_count(op, {3, 4});
validate_inputs_count(op, {4, 5});
auto inputs = p.GetInputInfo(op);
std::string primitive_name = layer_type_name_ID(op);
auto input_name = inputs[0].pid;
auto weights_name = inputs[1].pid;
auto scale_name = inputs[2].pid;
auto zp_name = inputs.size() == 4 ? inputs[3].pid : "";
auto bias_name = inputs[2].pid;
auto scale_name = inputs[3].pid;
auto zp_name = inputs.size() == 5 ? inputs[4].pid : "";
float zp_value = 0.0f;
bool has_scalar_zp = false;
@ -47,7 +48,7 @@ static void CreateFullyConnectedCompressedOp(ProgramBuilder& p, const std::share
auto fc = cldnn::fully_connected(primitive_name,
cldnn::input_info(input_name),
weights_name,
"",
bias_name,
scale_name,
has_scalar_zp ? "" : zp_name,
cldnn::element_type_to_data_type(op->get_output_element_type(0)),
@ -63,12 +64,13 @@ static void CreateFullyConnectedCompressedOp(ProgramBuilder& p, const std::share
}
static void CreateFullyConnectedOp(ProgramBuilder& p, const std::shared_ptr<op::FullyConnected>& op) {
validate_inputs_count(op, {2});
validate_inputs_count(op, {3});
auto inputs = p.GetInputInfo(op);
std::string layerName = layer_type_name_ID(op);
auto input_name = inputs[0].pid;
auto weights_name = inputs[1].pid;
auto bias_name = inputs[2].pid;
auto shape_a = op->get_input_partial_shape(0);
auto shape_b = op->get_input_partial_shape(1);
@ -79,7 +81,7 @@ static void CreateFullyConnectedOp(ProgramBuilder& p, const std::shared_ptr<op::
auto fcPrim = cldnn::fully_connected(layerName,
cldnn::input_info(input_name),
weights_name,
"",
bias_name,
cldnn::element_type_to_data_type(op->get_output_element_type(0)),
cldnn::padding(),
rank_a,

View File

@ -59,14 +59,16 @@ ConvertFullyConnectedToFullyConnectedCompressed::ConvertFullyConnectedToFullyCon
auto transpose_m = wrap_type<ov::op::v1::Transpose>({transpose_input, transpose_const_m});
auto data_m = any_input();
auto bias_m = any_input();
auto weights_input_m = std::make_shared<ov::pass::pattern::op::Or>(ov::OutputVector{reshape_m, transpose_m, mul_m});
auto fully_connected_m = wrap_type<op::FullyConnected>({data_m, weights_input_m});
auto fully_connected_m = wrap_type<op::FullyConnected>({data_m, weights_input_m, bias_m});
ov::matcher_pass_callback callback = [=](ov::pass::pattern::Matcher& m) {
const auto& pattern_map = m.get_pattern_value_map();
OPENVINO_ASSERT(pattern_map.count(fully_connected_m));
OPENVINO_ASSERT(pattern_map.count(mul_const_m));
OPENVINO_ASSERT(pattern_map.count(weights_m));
OPENVINO_ASSERT(pattern_map.count(bias_m));
OPENVINO_ASSERT(pattern_map.count(convert_m));
auto fc = std::dynamic_pointer_cast<op::FullyConnected>(pattern_map.at(fully_connected_m).get_node_shared_ptr());
if (!fc || transformation_callback(fc)) {
@ -103,6 +105,7 @@ ConvertFullyConnectedToFullyConnectedCompressed::ConvertFullyConnectedToFullyCon
std::shared_ptr<ov::Node> fc_input_b = reshape_const_to_2d(pattern_map.at(weights_m).get_node_shared_ptr());
std::shared_ptr<ov::Node> fc_input_scale = scale;
std::shared_ptr<ov::Node> fc_input_zp = optional_zero_point;
std::shared_ptr<ov::Node> fc_input_bias = pattern_map.at(bias_m).get_node_shared_ptr();
std::vector<std::shared_ptr<ov::Node>> result_nodes = {};
if (has_transpose) {
const auto& transpose = pattern_map.at(transpose_m).get_node_shared_ptr();
@ -128,12 +131,14 @@ ConvertFullyConnectedToFullyConnectedCompressed::ConvertFullyConnectedToFullyCon
if (with_zero_point) {
new_fc = std::make_shared<op::FullyConnectedCompressed>(fc_input_a,
fc_input_b,
fc_input_bias,
fc_input_scale,
fc_input_zp,
fc->get_output_type());
} else {
new_fc = std::make_shared<op::FullyConnectedCompressed>(fc_input_a,
fc_input_b,
fc_input_bias,
fc_input_scale,
fc->get_output_type());
}

View File

@ -3,6 +3,7 @@
//
#include "intel_gpu/op/fully_connected.hpp"
#include "intel_gpu/op/placeholder.hpp"
#include "convert_matmul_to_fc.hpp"
#include "openvino/op/matmul.hpp"
#include "openvino/op/convert.hpp"
@ -177,8 +178,10 @@ ConvertMatMulToFullyConnected::ConvertMatMulToFullyConnected() {
fc_input_b = convert;
}
auto no_bias = std::make_shared<op::Placeholder>();
// Create FullyConnected
auto fc = std::make_shared<op::FullyConnected>(fc_input_a, fc_input_b, matmul->get_output_element_type(0));
auto fc = std::make_shared<op::FullyConnected>(fc_input_a, fc_input_b, no_bias, matmul->get_output_element_type(0));
fc->set_friendly_name(matmul->get_friendly_name());
new_ops.push_back(fc);
ov::copy_runtime_info(matmul, new_ops);

View File

@ -20,8 +20,9 @@ FullyConnectedConvertFusion::FullyConnectedConvertFusion() {
auto data = any_input();
auto weights = any_input();
auto fully_connected = wrap_type<op::FullyConnected>({data, weights}, consumers_count(1));
auto fully_connected_compressed = wrap_type<op::FullyConnectedCompressed>({data, weights, any_input(), any_input()}, consumers_count(1));
auto bias = any_input();
auto fully_connected = wrap_type<op::FullyConnected>({data, weights, bias}, consumers_count(1));
auto fully_connected_compressed = wrap_type<op::FullyConnectedCompressed>({data, weights, bias, any_input(), any_input()}, consumers_count(1));
auto fc = std::make_shared<ov::pass::pattern::op::Or>(OutputVector{fully_connected, fully_connected_compressed});
auto convert = wrap_type<ov::op::v0::Convert>({fc}, type_matches(element::f32));
@ -30,6 +31,7 @@ FullyConnectedConvertFusion::FullyConnectedConvertFusion() {
const auto& m_data = pattern_map.at(data).get_node_shared_ptr();
const auto& m_weights = pattern_map.at(weights).get_node_shared_ptr();
const auto& m_bias = pattern_map.at(bias).get_node_shared_ptr();
const auto& m_convert = pattern_map.at(convert).get_node_shared_ptr();
auto output_type = m_convert->get_output_element_type(0);
@ -38,13 +40,14 @@ FullyConnectedConvertFusion::FullyConnectedConvertFusion() {
auto it = pattern_map.find(fully_connected);
if (it != pattern_map.end()) {
m_fc = it->second.get_node_shared_ptr();
new_fc = std::make_shared<op::FullyConnected>(m_data, m_weights, output_type);
new_fc = std::make_shared<op::FullyConnected>(m_data, m_weights, m_bias, output_type);
} else {
m_fc = pattern_map.at(fully_connected_compressed).get_node_shared_ptr();
new_fc = std::make_shared<op::FullyConnectedCompressed>(m_data,
m_weights,
m_fc->input_value(2),
m_bias,
m_fc->input_value(3),
m_fc->input_value(4),
output_type);
}
new_fc->set_friendly_name(m_convert->get_friendly_name());

View File

@ -44,7 +44,7 @@ MoveFCReshapeToWeights::MoveFCReshapeToWeights() {
auto weights_input_m = std::make_shared<ov::pass::pattern::op::Or>(ov::OutputVector{reshape_m, transpose_m});
auto data_m = any_input();
auto fully_connected_m = wrap_type<op::FullyConnected>({data_m, weights_input_m});
auto fully_connected_m = wrap_type<op::FullyConnected>({data_m, weights_input_m, any_input()});
ov::matcher_pass_callback callback = [&](ov::pass::pattern::Matcher& m) {
const auto fully_connected = m.get_match_root();

View File

@ -11,24 +11,25 @@ namespace op {
FullyConnected::FullyConnected(const ov::Output<Node>& A,
const ov::Output<Node>& B,
const ov::Output<Node>& bias,
const ov::element::Type output_type)
: Op({A, B}), m_output_type(output_type) {
: Op({A, B, bias}), m_output_type(output_type) {
validate_and_infer_types();
}
std::shared_ptr<ov::Node> FullyConnected::clone_with_new_inputs(const ov::OutputVector& new_args) const {
check_new_args_count(this, new_args);
return std::make_shared<FullyConnected>(new_args.at(0), new_args.at(1), m_output_type);
return std::make_shared<FullyConnected>(new_args.at(0), new_args.at(1), new_args.at(2), m_output_type);
}
void FullyConnected::validate_and_infer_types() {
const auto input_size = get_input_size();
NODE_VALIDATION_CHECK(this,
input_size >= 2,
input_size >= 3,
"Number of inputs is incorrect. Current value is: ",
input_size,
", expected at least 2.");
", expected at least 3.");
ov::op::v0::MatMul op;
op.set_transpose_a(false);

View File

@ -10,38 +10,42 @@ namespace op {
FullyConnectedCompressed::FullyConnectedCompressed(const ov::Output<Node>& A,
const ov::Output<Node>& B,
const ov::Output<Node>& bias,
const ov::Output<Node>& decompression_scale,
const ov::Output<Node>& decompression_zero_point,
const ov::element::Type output_type)
: FullyConnected(A, B, output_type) {
set_argument(2, decompression_scale);
set_argument(3, decompression_zero_point);
: FullyConnected(A, B, bias, output_type) {
set_argument(3, decompression_scale);
set_argument(4, decompression_zero_point);
validate_and_infer_types();
}
FullyConnectedCompressed::FullyConnectedCompressed(const ov::Output<Node>& A,
const ov::Output<Node>& B,
const ov::Output<Node>& bias,
const ov::Output<Node>& decompression_scale,
const ov::element::Type output_type)
: FullyConnected(A, B, output_type) {
set_argument(2, decompression_scale);
: FullyConnected(A, B, bias, output_type) {
set_argument(3, decompression_scale);
validate_and_infer_types();
}
std::shared_ptr<ov::Node> FullyConnectedCompressed::clone_with_new_inputs(const ov::OutputVector& new_args) const {
check_new_args_count(this, new_args);
if (new_args.size() == 3)
return std::make_shared<FullyConnectedCompressed>(new_args.at(0),
new_args.at(1),
new_args.at(2),
m_output_type);
else if (new_args.size() == 4)
if (new_args.size() == 4)
return std::make_shared<FullyConnectedCompressed>(new_args.at(0),
new_args.at(1),
new_args.at(2),
new_args.at(3),
m_output_type);
else if (new_args.size() == 5)
return std::make_shared<FullyConnectedCompressed>(new_args.at(0),
new_args.at(1),
new_args.at(2),
new_args.at(3),
new_args.at(4),
m_output_type);
else
OPENVINO_THROW("Unexpected inputs count for FullyConnectedCompressed op: ", new_args.size());
}

View File

@ -17,6 +17,7 @@
#include "openvino/op/add.hpp"
#include "intel_gpu/op/fully_connected.hpp"
#include "intel_gpu/op/fully_connected_compressed.hpp"
#include "intel_gpu/op/placeholder.hpp"
#include "plugin/transformations/convert_fc_to_compressed.hpp"
@ -36,7 +37,8 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed1) {
auto convert = std::make_shared<ov::op::v0::Convert>(weights_const, ov::element::f32);
auto scale_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 32, 1 }, { 1 });
auto scale = std::make_shared<ov::op::v1::Multiply>(convert, scale_const);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, scale);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, scale, no_bias);
model = std::make_shared<ov::Model>(ov::NodeVector{ fc }, ov::ParameterVector{ input1 });
manager.register_pass<ConvertFullyConnectedToFullyConnectedCompressed>();
@ -44,8 +46,9 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed1) {
{
auto input1 = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::PartialShape{ -1, 16 });
auto weights_const = ov::op::v0::Constant::create(ov::element::u8, ov::Shape{ 32, 16 }, { 1 });
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 32, 1 }, { 1 });
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, weights_const, scale_const);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, weights_const, no_bias, scale_const);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ fc_compressed }, ov::ParameterVector{ input1 });
}
@ -60,7 +63,8 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed2) {
auto sub = std::make_shared<ov::op::v1::Subtract>(convert, zp_const);
auto scale_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 32, 1 }, { 1 });
auto scale = std::make_shared<ov::op::v1::Multiply>(sub, scale_const);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, scale);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, scale, no_bias);
model = std::make_shared<ov::Model>(ov::NodeVector{ fc }, ov::ParameterVector{ input1 });
manager.register_pass<ConvertFullyConnectedToFullyConnectedCompressed>();
@ -68,9 +72,10 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed2) {
{
auto input1 = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::PartialShape{ -1, 16 });
auto weights_const = ov::op::v0::Constant::create(ov::element::u8, ov::Shape{ 32, 16 }, { 1 });
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 32, 1 }, { 1 });
auto zp_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 32, 1 }, { 1 });
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, weights_const, scale_const, zp_const);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, weights_const, no_bias, scale_const, zp_const);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ fc_compressed }, ov::ParameterVector{ input1 });
}
@ -87,7 +92,8 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed3) {
auto scale = std::make_shared<ov::op::v1::Multiply>(sub, scale_const);
auto reshape_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { -1, 16 });
auto reshape = std::make_shared<ov::op::v1::Reshape>(scale, reshape_const, false);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, reshape);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, reshape, no_bias);
model = std::make_shared<ov::Model>(ov::NodeVector{ fc }, ov::ParameterVector{ input1 });
manager.register_pass<ConvertFullyConnectedToFullyConnectedCompressed>();
@ -95,9 +101,10 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed3) {
{
auto input1 = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::PartialShape{ -1, 16 });
auto weights_const = ov::op::v0::Constant::create(ov::element::u8, ov::Shape{ 32, 16 }, { 1 });
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 32, 4 }, { 1 });
auto zp_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 32, 4 }, { 1 });
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, weights_const, scale_const, zp_const);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, weights_const, no_bias, scale_const, zp_const);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ fc_compressed }, ov::ParameterVector{ input1 });
}
@ -114,7 +121,8 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed4) {
auto scale = std::make_shared<ov::op::v1::Multiply>(sub, scale_const);
auto reshape_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { -1, 16 });
auto reshape = std::make_shared<ov::op::v1::Reshape>(scale, reshape_const, false);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, reshape);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, reshape, no_bias);
model = std::make_shared<ov::Model>(ov::NodeVector{ fc }, ov::ParameterVector{ input1 });
manager.register_pass<ConvertFullyConnectedToFullyConnectedCompressed>();
@ -122,9 +130,10 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed4) {
{
auto input1 = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::PartialShape{ -1, 16 });
auto weights_const = ov::op::v0::Constant::create(ov::element::u4, ov::Shape{ 32, 16 }, { 1 });
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 32, 4 }, { 1 });
auto zp_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 1, 1 }, { 1 });
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, weights_const, scale_const, zp_const);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, weights_const, no_bias, scale_const, zp_const);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ fc_compressed }, ov::ParameterVector{ input1 });
}
@ -143,7 +152,8 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed5) {
auto reshape = std::make_shared<ov::op::v1::Reshape>(scale, reshape_const, false);
auto transpose_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose = std::make_shared<ov::op::v1::Transpose>(reshape, transpose_const);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, transpose);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, transpose, no_bias);
model = std::make_shared<ov::Model>(ov::NodeVector{ fc }, ov::ParameterVector{ input1 });
manager.register_pass<ConvertFullyConnectedToFullyConnectedCompressed>();
@ -153,11 +163,12 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed5) {
auto weights_const = ov::op::v0::Constant::create(ov::element::u4, ov::Shape{ 16, 32 }, { 1 });
auto transpose_weights_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_weights = std::make_shared<ov::op::v1::Transpose>(weights_const, transpose_weights_const);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 4, 32 }, { 1 });
auto transpose_scale_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_scale = std::make_shared<ov::op::v1::Transpose>(scale_const, transpose_scale_const);
auto zp_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 1, 1 }, { 1 });
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, transpose_weights, transpose_scale, zp_const);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, transpose_weights, no_bias, transpose_scale, zp_const);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ fc_compressed }, ov::ParameterVector{ input1 });
}
@ -176,7 +187,8 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed6) {
auto reshape = std::make_shared<ov::op::v1::Reshape>(scale, reshape_const, false);
auto transpose_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose = std::make_shared<ov::op::v1::Transpose>(reshape, transpose_const);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, transpose);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, transpose, no_bias);
model = std::make_shared<ov::Model>(ov::NodeVector{ fc }, ov::ParameterVector{ input1 });
manager.register_pass<ConvertFullyConnectedToFullyConnectedCompressed>();
@ -186,13 +198,14 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed6) {
auto weights_const = ov::op::v0::Constant::create(ov::element::u4, ov::Shape{ 16, 32 }, { 1 });
auto transpose_weights_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_weights = std::make_shared<ov::op::v1::Transpose>(weights_const, transpose_weights_const);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 4, 32 }, { 1 });
auto transpose_scale_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_scale = std::make_shared<ov::op::v1::Transpose>(scale_const, transpose_scale_const);
auto zp_const = ov::op::v0::Constant::create(ov::element::f32, ov::Shape{ 4, 32 }, { 1 });
auto transpose_zp_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_zp = std::make_shared<ov::op::v1::Transpose>(zp_const, transpose_zp_const);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, transpose_weights, transpose_scale, transpose_zp);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, transpose_weights, no_bias, transpose_scale, transpose_zp);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ fc_compressed }, ov::ParameterVector{ input1 });
}
@ -211,7 +224,8 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed7) {
auto reshape = std::make_shared<ov::op::v1::Reshape>(scale, reshape_const, false);
auto transpose_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose = std::make_shared<ov::op::v1::Transpose>(reshape, transpose_const);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, transpose);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(input1, transpose, no_bias);
model = std::make_shared<ov::Model>(ov::NodeVector{ fc }, ov::ParameterVector{ input1 });
manager.register_pass<ConvertFullyConnectedToFullyConnectedCompressed>();
@ -221,13 +235,14 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed7) {
auto weights_const = ov::op::v0::Constant::create(ov::element::u4, ov::Shape{ 16, 32 }, { 1 });
auto transpose_weights_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_weights = std::make_shared<ov::op::v1::Transpose>(weights_const, transpose_weights_const);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{ 4, 32 }, { 1 });
auto transpose_scale_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_scale = std::make_shared<ov::op::v1::Transpose>(scale_const, transpose_scale_const);
auto zp_const = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{ 4, 32 }, { 1 });
auto transpose_zp_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_zp = std::make_shared<ov::op::v1::Transpose>(zp_const, transpose_zp_const);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, transpose_weights, transpose_scale, transpose_zp);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input1, transpose_weights, no_bias, transpose_scale, transpose_zp);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ fc_compressed }, ov::ParameterVector{ input1 });
}
@ -325,6 +340,7 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed8) {
auto reshape = std::make_shared<ov::op::v1::Reshape>(scale, reshape_const, false);
auto transpose_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose = std::make_shared<ov::op::v1::Transpose>(reshape, transpose_const);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto param1 = std::make_shared<ov::op::v0::Parameter>(ov::element::f16, ov::PartialShape{-1, 15});
auto const_value1 = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{1, 1}, {1});
@ -344,7 +360,7 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed8) {
args[i] = subgraph_parameters[i]->output(0);
}
auto subgraph_op = std::make_shared<TestSubgraph>(args, submodel);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(subgraph_op->output(1), transpose);
auto fc = std::make_shared<ov::intel_gpu::op::FullyConnected>(subgraph_op->output(1), transpose, no_bias);
model = std::make_shared<ov::Model>(ov::NodeVector{std::make_shared<ov::op::v0::Result>(subgraph_op->output(0)), fc}, subgraph_parameters);
manager.register_pass<ConvertFullyConnectedToFullyConnectedCompressed>();
@ -353,6 +369,7 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed8) {
auto weights_const = ov::op::v0::Constant::create(ov::element::u4, ov::Shape{ 16, 32 }, { 1 });
auto transpose_weights_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_weights = std::make_shared<ov::op::v1::Transpose>(weights_const, transpose_weights_const);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{ 4, 32 }, { 1 });
auto transpose_scale_const = ov::op::v0::Constant::create(ov::element::i32, ov::Shape{ 2 }, { 1, 0 });
auto transpose_scale = std::make_shared<ov::op::v1::Transpose>(scale_const, transpose_scale_const);
@ -378,7 +395,7 @@ TEST_F(TransformationTestsF, ConvertFCToCompressed8) {
args[i] = subgraph_parameters[i]->output(0);
}
auto subgraph_op = std::make_shared<TestSubgraph>(args, submodel);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(subgraph_op->output(1), transpose_weights, transpose_scale, transpose_zp);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(subgraph_op->output(1), transpose_weights, no_bias, transpose_scale, transpose_zp);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ std::make_shared<ov::op::v0::Result>(subgraph_op->output(0)), fc_compressed }, subgraph_parameters);
}

View File

@ -12,6 +12,7 @@
#include <openvino/opsets/opset3.hpp>
#include <openvino/opsets/opset7.hpp>
#include <intel_gpu/op/fully_connected.hpp>
#include <intel_gpu/op/placeholder.hpp>
#include <plugin/transformations/convert_matmul_to_fc.hpp>
#include <transformations/init_node_info.hpp>
#include <transformations/utils/utils.hpp>
@ -42,7 +43,9 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest1) {
auto transpose_constant2 = ov::opset1::Constant::create(ov::element::i32, ov::Shape{ 3 }, { 0, 2, 1 });
auto transpose2 = std::make_shared<ov::opset1::Transpose>(input2, transpose_constant2);
auto matmul = std::make_shared<op::FullyConnected>(transpose1, transpose2);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(transpose1, transpose2, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ matmul }, ov::ParameterVector{ input1 });
}
@ -78,7 +81,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest3) {
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::Shape{3, 2, 2});
auto input2 = ov::opset1::Constant::create(ov::element::f32, ov::Shape{2, 2}, {1});
auto matmul = std::make_shared<op::FullyConnected>(input1, input2);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input1});
}
@ -96,7 +100,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest4) {
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::PartialShape{-1, -1, 2});
auto input2 = ov::opset1::Constant::create(ov::element::f32, ov::Shape{2, 2}, {1});
auto matmul = std::make_shared<op::FullyConnected>(input1, input2);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input1});
}
@ -132,7 +137,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest7) {
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::Shape{3, 2, 2});
auto input2 = ov::opset1::Constant::create(ov::element::f32, ov::Shape{3, 2}, {1});
auto fc = std::make_shared<op::FullyConnected>(input1, input2);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<op::FullyConnected>(input1, input2, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{fc}, ov::ParameterVector{input1});
}
@ -150,8 +156,9 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest8) {
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::PartialShape{-1, -1, 2});
auto input2 = ov::opset1::Constant::create(ov::element::f32, ov::Shape{3, 2}, {1});
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fc = std::make_shared<op::FullyConnected>(input1, input2);
auto fc = std::make_shared<op::FullyConnected>(input1, input2, no_bias);
auto a_shape = std::make_shared<ov::opset3::ShapeOf>(input1);
auto I = ov::op::util::node_to_get_shape_value_of_indices_from_shape_node(a_shape, {0, 1});
@ -174,7 +181,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest9) {
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::Shape{3, 2, 2});
auto input2 = ov::opset1::Constant::create(ov::element::f32, ov::Shape{2, 2}, {1});
auto matmul = std::make_shared<op::FullyConnected>(input1, input2);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input1});
}
@ -219,7 +227,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest13) {
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::PartialShape{-1, -1, 1});
auto input2 = ov::opset1::Constant::create(ov::element::f32, ov::Shape{1, 80, 1}, {1});
auto matmul = std::make_shared<op::FullyConnected>(input1, input2);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input1});
}
@ -243,7 +252,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest14) {
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::u8, ov::PartialShape{-1, -1, 1});
auto input2 = ov::opset1::Constant::create(ov::element::i8, ov::Shape{1, 80, 1}, {1});
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, ov::element::f32);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, no_bias, ov::element::f32);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input1});
}
@ -272,9 +282,10 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest15) {
auto transpose_constant = ov::opset1::Constant::create(ov::element::i32, ov::Shape{2}, {1, 0});
auto transpose = std::make_shared<ov::opset1::Transpose>(input3, transpose_constant);
auto convert = std::make_shared<ov::opset1::Convert>(transpose, ov::element::f32);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul1 = std::make_shared<op::FullyConnected>(input1, convert);
auto matmul2 = std::make_shared<op::FullyConnected>(input2, convert);
auto matmul1 = std::make_shared<op::FullyConnected>(input1, convert, no_bias);
auto matmul2 = std::make_shared<op::FullyConnected>(input2, convert, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{matmul1, matmul2}, ov::ParameterVector{input1, input2});
}
@ -292,7 +303,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest_second_input_rank
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::Shape{5, 2, 3});
auto input2 = ov::opset1::Constant::create(ov::element::f32, ov::Shape{1, 2, 3}, {1});
auto matmul = std::make_shared<op::FullyConnected>(input1, input2);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input1});
}
}
@ -309,7 +321,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest_second_input_rank
{
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::Shape{ 2, 3 });
auto weights = ov::opset1::Constant::create(ov::element::f32, ov::Shape{ 2, 3 }, { 1 });
auto matmul = std::make_shared<op::FullyConnected>(input1, weights);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, weights, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ matmul }, ov::ParameterVector{ input1 });
}
@ -328,7 +341,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest_second_input_rank
auto input1 = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::Shape{ 5, 2, 3 });
auto weights = ov::opset1::Constant::create(ov::element::f32, ov::Shape{ 1, 2, 3 }, { 1 });
auto matmul = std::make_shared<op::FullyConnected>(input1, weights);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, weights, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ matmul }, ov::ParameterVector{ input1 });
}
}
@ -351,8 +365,9 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest_decompress_conver
auto transpose_constant = ov::opset1::Constant::create(ov::element::i32, ov::Shape{ 3 }, { 0, 2, 1 });
auto transpose = std::make_shared<ov::opset1::Transpose>(input2, transpose_constant);
auto convert = std::make_shared<ov::opset1::Convert>(transpose, ov::element::f32);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, convert);
auto matmul = std::make_shared<op::FullyConnected>(input1, convert, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ matmul }, ov::ParameterVector{ input1 });
}
@ -378,8 +393,9 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest_decompress_conver
auto transpose_constant2 = ov::opset1::Constant::create(ov::element::i32, ov::Shape{ 3 }, { 0, 2, 1 });
auto transpose2 = std::make_shared<ov::opset1::Transpose>(input2, transpose_constant2);
auto convert = std::make_shared<ov::opset1::Convert>(transpose2, ov::element::f32);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(transpose1, convert);
auto matmul = std::make_shared<op::FullyConnected>(transpose1, convert, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ matmul }, ov::ParameterVector{ input1 });
}
@ -410,7 +426,8 @@ TEST_F(TransformationTestsF, ConvertMatMulToFullyConnectedTest_compressed_u8_wei
auto transpose_const = ov::opset1::Constant::create(ov::element::i32, {3}, {0, 2, 1});
auto transpose = std::make_shared<ov::opset1::Transpose>(mul, transpose_const);
auto matmul = std::make_shared<op::FullyConnected>(data, transpose);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(data, transpose, no_bias);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ matmul }, ov::ParameterVector{ data });
}

View File

@ -19,6 +19,7 @@
#include "openvino/op/parameter.hpp"
#include "intel_gpu/op/fully_connected.hpp"
#include "intel_gpu/op/fully_connected_compressed.hpp"
#include "intel_gpu/op/placeholder.hpp"
using namespace testing;
using namespace ov::intel_gpu;
@ -27,9 +28,10 @@ TEST_F(TransformationTestsF, FullyConnectedConvertFusionTest1) {
{
auto input = std::make_shared<ov::op::v0::Parameter>(ov::element::f16, ov::PartialShape{ -1, 16 });
auto weights_const = ov::op::v0::Constant::create(ov::element::u8, ov::Shape{ 32, 16 }, { 1 });
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{ 32, 1 }, { 1 });
auto zp_const = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{ 32, 1 }, { 1 });
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input, weights_const, scale_const, zp_const);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input, weights_const, no_bias, scale_const, zp_const);
auto convert = std::make_shared<ov::op::v0::Convert>(fc_compressed, ov::element::f32);
model = std::make_shared<ov::Model>(ov::NodeVector{convert}, ov::ParameterVector{input});
@ -38,9 +40,10 @@ TEST_F(TransformationTestsF, FullyConnectedConvertFusionTest1) {
{
auto input = std::make_shared<ov::op::v0::Parameter>(ov::element::f16, ov::PartialShape{ -1, 16 });
auto weights_const = ov::op::v0::Constant::create(ov::element::u8, ov::Shape{ 32, 16 }, { 1 });
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto scale_const = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{ 32, 1 }, { 1 });
auto zp_const = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{ 32, 1 }, { 1 });
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input, weights_const, scale_const, zp_const, ov::element::f32);
auto fc_compressed = std::make_shared<ov::intel_gpu::op::FullyConnectedCompressed>(input, weights_const, no_bias, scale_const, zp_const, ov::element::f32);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ fc_compressed }, ov::ParameterVector{ input });
}
@ -50,7 +53,8 @@ TEST_F(TransformationTestsF, FullyConnectedConvertFusionTest2) {
{
auto input1 = std::make_shared<ov::op::v0::Parameter>(ov::element::f16, ov::Shape{3, 2, 2});
auto input2 = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{2, 2}, {1});
auto matmul = std::make_shared<op::FullyConnected>(input1, input2);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, no_bias);
auto convert = std::make_shared<ov::op::v0::Convert>(matmul, ov::element::f32);
model = std::make_shared<ov::Model>(ov::NodeVector{convert}, ov::ParameterVector{input1});
@ -59,7 +63,8 @@ TEST_F(TransformationTestsF, FullyConnectedConvertFusionTest2) {
{
auto input1 = std::make_shared<ov::op::v0::Parameter>(ov::element::f16, ov::Shape{3, 2, 2});
auto input2 = ov::op::v0::Constant::create(ov::element::f16, ov::Shape{2, 2}, {1});
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, ov::element::f32);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto matmul = std::make_shared<op::FullyConnected>(input1, input2, no_bias, ov::element::f32);
model_ref = std::make_shared<ov::Model>(ov::NodeVector{ matmul }, ov::ParameterVector{ input1 });
}

View File

@ -12,6 +12,7 @@
#include <openvino/core/model.hpp>
#include <openvino/opsets/opset1.hpp>
#include <intel_gpu/op/fully_connected.hpp>
#include <intel_gpu/op/placeholder.hpp>
#include <transformations/init_node_info.hpp>
#include <transformations/utils/utils.hpp>
@ -71,7 +72,9 @@ public:
auto transpose_const = ov::opset1::Constant::create(ov::element::i32, {2}, {1, 0});
weights_path = std::make_shared<ov::opset1::Transpose>(weights_path, transpose_const);
}
auto fully_connected = std::make_shared<op::FullyConnected>(data, weights_path);
auto no_bias = std::make_shared<ov::intel_gpu::op::Placeholder>();
auto fully_connected = std::make_shared<op::FullyConnected>(data, weights_path, no_bias);
return std::make_shared<ov::Model>(ov::NodeVector{fully_connected}, ov::ParameterVector{data});
}