Skip to content

Commit

Permalink
[ONNX] Added FusedMatMul from com.microsoft domain (#27556)
Browse files Browse the repository at this point in the history
Details:
Microsoft Contrib Operator "FusedMatMul" for ONNX RT

Tickets:
N/A

---------

Co-authored-by: Georgy Krivoruchko <[email protected]>
  • Loading branch information
vatsalashanubhag and gkrivor authored Nov 26, 2024
1 parent adde531 commit 54c2f60
Show file tree
Hide file tree
Showing 4 changed files with 319 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/frontends/onnx/frontend/src/op/com.microsoft/fusedmatmul.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "cmath"
#include "core/operator_set.hpp"
#include "exceptions.hpp"
#include "openvino/frontend/exception.hpp"
#include "openvino/op/constant.hpp"
#include "openvino/op/matmul.hpp"
#include "openvino/op/multiply.hpp"
#include "openvino/op/transpose.hpp"
#include "utils/common.hpp"

using namespace ov::op;

namespace ov {
namespace frontend {
namespace onnx {
namespace com_microsoft {
namespace opset_1 {

std::vector<size_t> get_transpose_axes(size_t rank) {
std::vector<size_t> axes(rank);
std::iota(axes.begin(), axes.end(), 0);

if (rank > 2) {
std::rotate(axes.begin() + 1, axes.begin() + 2, axes.begin() + rank - 1);
}
return axes;
}

ov::OutputVector fusedmatmul(const ov::frontend::onnx::Node& node) {
common::default_op_checks(node, 2);

const auto inputs = node.get_ov_inputs();
auto A = inputs[0]; // required
auto B = inputs[1]; // required

const auto alpha = node.get_attribute_value<float>("alpha"); // required
const auto transA = node.get_attribute_value<int64_t>("transA"); // required
const auto transB = node.get_attribute_value<int64_t>("transB"); // required
const auto transBatchA = node.get_attribute_value<int64_t>("transBatchA"); // required
const auto transBatchB = node.get_attribute_value<int64_t>("transBatchB"); // required

CHECK_VALID_NODE(node,
A.get_element_type() == ov::element::f16 || A.get_element_type() == ov::element::f32 ||
A.get_element_type() == ov::element::f64 || A.get_element_type() == ov::element::bf16,
"Unsupported input A type, accepted FP16, FP32, FP64, BFP16 got: ",
A.get_element_type());
CHECK_VALID_NODE(node,
B.get_element_type() == ov::element::f16 || B.get_element_type() == ov::element::f32 ||
B.get_element_type() == ov::element::f64 || B.get_element_type() == ov::element::bf16,
"Unsupported input B type, accepted FP16, FP32, FP64, BFP16 got: ",
B.get_element_type());

const auto rankA = A.get_shape().size();
const auto rankB = B.get_shape().size();

if (transBatchA) {
A = std::make_shared<v1::Transpose>(
A,
std::make_shared<v0::Constant>(element::i64, Shape{rankA}, get_transpose_axes(rankA)));
}

if (transBatchB) {
B = std::make_shared<v1::Transpose>(
B,
std::make_shared<v0::Constant>(element::i64, Shape{rankB}, get_transpose_axes(rankB)));
}

auto matmul_result = std::make_shared<v0::MatMul>(A, B, transA, transB);

auto alpha_const = std::make_shared<v0::Constant>(A.get_element_type(), Shape{}, std::vector<float>{alpha});
auto scaled_result = std::make_shared<v1::Multiply>(matmul_result, alpha_const);

return {scaled_result};
}

ONNX_OP("FusedMatMul", OPSET_SINCE(1), com_microsoft::opset_1::fusedmatmul, MICROSOFT_DOMAIN);

} // namespace opset_1
} // namespace com_microsoft
} // namespace onnx
} // namespace frontend
} // namespace ov
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
ir_version: 3
producer_name: "OpenVINO ONNX Frontend"
model_version: 0
graph {
name: "FusedMatMulModel"
node {
op_type: "FusedMatMul"
input: "A"
input: "B"
output: "output"
attribute {
name: "alpha"
f: 0.75
type: FLOAT
}
attribute {
name: "transA"
i: 1
type: INT
}
attribute {
name: "transB"
i: 0
type: INT
}
attribute {
name: "transBatchA"
i: 0
type: INT
}
attribute {
name: "transBatchB"
i: 0
type: INT
}
domain: "com.microsoft"
}
input {
name: "A"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 3
}
dim {
dim_value: 2
}
}
}
}
}
input {
name: "B"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 3
}
dim {
dim_value: 2
}
}
}
}
}
output {
name: "output"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
dim {
dim_value: 2
}
}
}
}
}
}
opset_import {
version: 7
}
opset_import {
version: 1
domain: "com.microsoft"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
ir_version: 3
producer_name: "OpenVINO ONNX Frontend"
model_version: 0
graph {
name: "FusedMatMulModel"
node {
op_type: "FusedMatMul"
input: "A"
input: "B"
output: "output"
attribute {
name: "alpha"
f: 0.5
type: FLOAT
}
attribute {
name: "transA"
i: 1
type: INT
}
attribute {
name: "transB"
i: 1
type: INT
}
attribute {
name: "transBatchA"
i: 1
type: INT
}
attribute {
name: "transBatchB"
i: 1
type: INT
}
domain: "com.microsoft"
}
input {
name: "A"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
dim {
dim_value: 5
}
dim {
dim_value: 4
}
}
}
}
}
input {
name: "B"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
dim {
dim_value: 3
}
dim {
dim_value: 5
}
}
}
}
}
output {
name: "output"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
dim {
dim_value: 4
}
dim {
dim_value: 3
}
}
}
}
}
}
opset_import {
version: 7
}
opset_import {
version: 1
domain: "com.microsoft"
}
39 changes: 39 additions & 0 deletions src/frontends/onnx/tests/onnx_import_com_microsoft.in.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1417,3 +1417,42 @@ OPENVINO_TEST(${BACKEND_NAME}, onnx_com_microsoft_simplified_layer_normalization

test_case.run();
}

OPENVINO_TEST(${BACKEND_NAME}, onnx_com_microsoft_fusedmatmul_2x3) {
const auto model = convert_model("com.microsoft/fusedmatmul_2D.onnx");
auto test_case = ov::test::TestCase(model, s_device);

const std::vector<float> data_A{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
const std::vector<float> data_B{7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f};
const std::vector<float> expected_output{66.75f, 73.5f, 87.f, 96.f};

test_case.add_input<float>(Shape{3, 2}, data_A);
test_case.add_input<float>(Shape{3, 2}, data_B);
test_case.add_expected_output<float>(Shape{2, 2}, expected_output);

test_case.run();
}

OPENVINO_TEST(${BACKEND_NAME}, onnx_com_microsoft_fusedmatmul_2x5x3x6x4_2x6x3x4x7) {
const auto model = convert_model("com.microsoft/fusedmatmul_trans_and_transbatch_enabled.onnx");
auto test_case = ov::test::TestCase(model, s_device);

const std::vector<float> data_A = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f,
11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f,
21.0f, 22.0f, 23.0f, 24.0f, 25.0f, 26.0f, 27.0f, 28.0f, 29.0f, 30.0f,
31.0f, 32.0f, 33.0f, 34.0f, 35.0f, 36.0f, 37.0f, 38.0f, 39.0f, 40.0f};

const std::vector<float> data_B = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f,
11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f,
21.0f, 22.0f, 23.0f, 24.0f, 25.0f, 26.0f, 27.0f, 28.0f, 29.0f, 30.0f};

const std::vector<float> expected_output = {87.5f, 200.0f, 312.5f, 95.0f, 220.0f, 345.0f, 102.5f, 240.0f,
377.5f, 110.0f, 260.0f, 410.0f, 1325.0f, 1687.5f, 2050.0f, 1370.0f,
1745.0f, 2120.0f, 1415.0f, 1802.5f, 2190.0f, 1460.0f, 1860.0f, 2260.0f};

test_case.add_input<float>(Shape{2, 5, 4}, data_A);
test_case.add_input<float>(Shape{2, 3, 5}, data_B);
test_case.add_expected_output<float>(Shape{2, 4, 3}, expected_output);

test_case.run();
}

0 comments on commit 54c2f60

Please sign in to comment.