#include "../node_context.h" #include "../op_table.h" #include "../utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ov { namespace frontend { namespace ggml { namespace op { OutputVector translate_mulmat(const NodeContext & context) { num_inputs_check(context, 2, 2); int op_case = context.get_op_case(); ov::Output res; ov::Output B; ov::Output A; if (op_case == 3) { B = process_view_input(context, 0); A = process_view_input(context, 1); } else { B = process_view_input_new(context, 0); A = process_view_input_new(context, 1); } if (A.get_element_type() != B.get_element_type()) { B = std::make_shared(context.get_input(0), context.get_input_type(1)); } auto B_shape = context.get_input_shape(0).to_shape(); auto A_shape = context.get_input_shape(1).to_shape(); int64_t A_batch = A_shape[1]; int64_t B_batch = B_shape[1]; auto A_batch_larger = A_batch > B_batch; auto batch_large = A_batch_larger ? A_batch : B_batch; auto batch_small = A_batch_larger ? B_batch : A_batch; Output Z = A_batch_larger ? B : A; auto Z_shape = A_batch_larger ? B_shape : A_shape; int64_t factor = batch_large / batch_small; if (factor > 1 && batch_small > 1) { auto batch_large_node = ov::op::v0::Constant::create(ov::element::i64, {1}, std::vector{batch_large}); auto batch_small_node = ov::op::v0::Constant::create(ov::element::i64, {1}, std::vector{batch_small}); auto factor_node = ov::op::v0::Constant::create(ov::element::i64, {1}, std::vector{factor}); auto unsqueeze_axes = ov::op::v0::Constant::create(ov::element::i64, Shape{}, {2}); auto Z_unsqueezed = std::make_shared(Z, unsqueeze_axes); auto broadcast_shape = ov::op::v0::Constant::create( ov::element::i64, {5}, {(int64_t) 1, (int64_t) 1, factor, (int64_t) 1, (int64_t) 1}); auto new_Z_shape = ov::op::v0::Constant::create(ov::element::i64, {4}, {(int64_t) 0, batch_large, (int64_t) -1, (int64_t) Z_shape[3]}); if (op_case == 2) { new_Z_shape = ov::op::v0::Constant::create(ov::element::i64, {4}, {(int64_t) 0, batch_large, (int64_t) Z_shape[2], (int64_t) -1}); } auto Z_broadcasted = std::make_shared(Z_unsqueezed, broadcast_shape, ov::op::BroadcastType::BIDIRECTIONAL); Z = std::make_shared(Z_broadcasted, new_Z_shape, true); } if (A_batch_larger) { B = Z; } else { A = Z; } bool transpose_b = true; res = std::make_shared(A, B, false, transpose_b); const auto output_type = context.get_output_type(); if (res.get_element_type() != output_type) { res = std::make_shared(res, output_type); } return rename_outputs_with_suffix({res}, context.get_name()); } } // namespace op } // namespace ggml } // namespace frontend } // namespace ov