Skip to content

Commit 7bc7a7f

Browse files
committed
Merge remote-tracking branch 'origin/master' into readability-avoid-nested-conditional-operator
2 parents 1f3ebb3 + 48c5506 commit 7bc7a7f

File tree

167 files changed

+2858
-1012
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

167 files changed

+2858
-1012
lines changed

docs/requirements.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
alabaster==0.7.16
22
atomicwrites==1.4.1
33
attrs==22.2.0
4-
Babel==2.11.0
4+
Babel==2.17.0
55
beautifulsoup4==4.9.3
66
breathe==4.36.0
77
certifi==2024.7.4
88
colorama==0.4.6
99
Cython==3.0.12
10-
docutils==0.20
10+
docutils==0.21.2
1111
idna==3.7
1212
imagesize==1.3.0
1313
importlib-metadata==4.8.0
@@ -18,9 +18,9 @@ jsonschema==4.23.0
1818
lxml>=4.9.2
1919
MarkupSafe==2.1.1
2020
mistune==2.0.3
21-
myst-parser==2.0.0
21+
myst-parser==4.0.1
2222
packaging==23.0
23-
pluggy==0.13.1
23+
pluggy==1.6.0
2424
pydata-sphinx-theme==0.14.4
2525
Pygments==2.15.1
2626
pyparsing==3.0.9

src/common/snippets/include/snippets/emitter.hpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ namespace snippets {
1616
* @interface RegType
1717
* @brief Register type of input and output operations
1818
*/
19-
enum class RegType { gpr, vec, mask, undefined };
19+
enum class RegType {
20+
gpr,
21+
vec,
22+
mask,
23+
// Ticket: 166071
24+
// Need to move this type to a separate class
25+
address, // address type should be ignored by the code generation logic, as it is handled outside the snippets pipeline.
26+
undefined
27+
};
2028
/**
2129
* @interface Reg
2230
* @brief Register representation: type of register and index
@@ -26,7 +34,8 @@ struct Reg {
2634
Reg() = default;
2735
Reg(RegType type_, size_t idx_) : type(type_), idx(idx_) {}
2836

29-
bool is_defined() const { return type != RegType::undefined && idx != UNDEFINED_IDX; }
37+
bool is_address() const { return type == RegType::address; }
38+
bool is_defined() const { return is_address() || (type != RegType::undefined && idx != UNDEFINED_IDX); }
3039
RegType type = RegType::undefined;
3140
size_t idx = UNDEFINED_IDX;
3241

src/common/snippets/include/snippets/lowered/port_descriptor.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ class PortDescriptor {
4444
void set_shape(const VectorDims& tensor);
4545
void set_layout(const std::vector<size_t>& layout);
4646
void set_subtensor(const VectorDims& subtensor);
47-
void set_reg(Reg reg) { m_reg = std::move(reg); }
48-
void set_reg_type(RegType type) { m_reg.type = type; }
49-
void set_reg_idx(size_t idx) { m_reg.idx = idx; }
47+
void set_reg(Reg reg);
48+
void set_reg_type(RegType type);
5049

5150
// Indexing starts from the end (rbegin() + idx)
5251
void set_subtensor_dim(size_t idx, VectorDims::value_type value);
@@ -92,6 +91,9 @@ class PortDescriptorUtils {
9291
static PortDescriptorPtr get_port_descriptor_ptr(const ov::Output<ov::Node>& out);
9392
static PortDescriptorPtr get_port_descriptor_ptr(const ov::Output<const ov::Node>& out);
9493

94+
static void set_address_reg_type(const ov::Input<ov::Node>& in);
95+
static void set_address_reg_type(const ov::Output<ov::Node>& out);
96+
9597
static void clean(const std::shared_ptr<ov::Node>& node);
9698

9799
private:

src/common/snippets/include/snippets/op/brgemm.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Brgemm : virtual public modifier::MemoryAccess, public ov::op::Op {
4141
bool visit_attributes(AttributeVisitor& visitor) override;
4242

4343
protected:
44-
ov::element::Type get_output_type() const;
44+
virtual ov::element::Type get_output_type() const;
4545
std::vector<ov::PartialShape> get_planar_input_shapes(const std::vector<ov::Input<ov::Node>>& inputs) const;
4646
ov::PartialShape infer_output_partial_shape(const std::vector<ov::PartialShape>& input_shapes) const;
4747
ov::PartialShape get_planar_output_shape(const ov::PartialShape& output_shape) const;

src/common/snippets/include/snippets/op/scalar.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ class Scalar : public ov::op::v0::Constant {
3434
}
3535
Scalar& operator=(const Scalar&) = delete;
3636

37+
template <class T, class = typename std::enable_if<std::is_fundamental<T>::value>::type>
38+
T get_value() const {
39+
const auto vec = cast_vector<T>();
40+
OPENVINO_ASSERT(vec.size() == 1, "Scalar must have a single value");
41+
return vec[0];
42+
}
43+
3744
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
3845
void validate_and_infer_types() override;
3946
bool visit_attributes(AttributeVisitor& visitor) override;

src/common/snippets/include/snippets/pass/tokenization.hpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,23 @@ class SnippetsTokenization : public ov::pass::ModelPass {
6767
* @ingroup snippets
6868
*/
6969
struct Config {
70-
Config(size_t concurrency, size_t data_ptr_gpr_count, bool split_m_dimension, bool enable_transpose_on_output,
71-
bool dyn_mha_token, std::set<size_t> mha_transpose_ranks)
72-
: m_concurrency(concurrency), m_data_ptr_gpr_count(data_ptr_gpr_count), m_split_m_dimension(split_m_dimension),
73-
m_mha_token_enable_transpose_on_output(enable_transpose_on_output), m_is_dynamic_mha_token_enabled(dyn_mha_token),
74-
m_mha_supported_transpose_ranks(std::move(mha_transpose_ranks)) {
70+
using CanBeFusedAsPostOpPred = std::function<bool(const std::shared_ptr<const ov::op::v0::MatMul>&,
71+
const std::shared_ptr<const ov::Node>&)>;
72+
73+
Config(size_t concurrency,
74+
size_t data_ptr_gpr_count,
75+
bool split_m_dimension,
76+
bool enable_transpose_on_output,
77+
bool dyn_mha_token,
78+
std::set<size_t> mha_transpose_ranks,
79+
CanBeFusedAsPostOpPred can_be_fused_as_postop = nullptr)
80+
: m_concurrency(concurrency),
81+
m_data_ptr_gpr_count(data_ptr_gpr_count),
82+
m_split_m_dimension(split_m_dimension),
83+
m_mha_token_enable_transpose_on_output(enable_transpose_on_output),
84+
m_is_dynamic_mha_token_enabled(dyn_mha_token),
85+
m_mha_supported_transpose_ranks(std::move(mha_transpose_ranks)),
86+
m_can_be_fused_as_postop(can_be_fused_as_postop) {
7587
OPENVINO_ASSERT(concurrency > 0, "Concurrency should be greater than 0");
7688
OPENVINO_ASSERT(data_ptr_gpr_count > 0, "data_ptr_gpr_count should be greater than 0");
7789
}
@@ -104,6 +116,10 @@ class SnippetsTokenization : public ov::pass::ModelPass {
104116
return m_mha_supported_transpose_ranks;
105117
}
106118

119+
const CanBeFusedAsPostOpPred& get_can_be_fused_as_postop() const {
120+
return m_can_be_fused_as_postop;
121+
}
122+
107123
private:
108124
size_t m_concurrency = 0;
109125
// The number of gpr that can be used as data pointers for data nodes (Parameter (and non-Scalar Constants),
@@ -123,6 +139,9 @@ class SnippetsTokenization : public ov::pass::ModelPass {
123139
// Note that in general Snippets support Transpose of any ranks.
124140
// But at the moment Transpose is used only in MHA pattern where 3D and 4D tensors are supported.
125141
std::set<size_t> m_mha_supported_transpose_ranks = { 3, 4 };
142+
// Predicate that checks if the node can be fused as MatMul post-op.
143+
// It is currently used only in TokenizeMLPSeqSnippets
144+
CanBeFusedAsPostOpPred m_can_be_fused_as_postop = nullptr;
126145
};
127146

128147
SnippetsTokenization(const Config& config) : m_config(config) {}

src/common/snippets/include/snippets/utils/reg_utils.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ inline static std::vector<size_t> transform_snippets_regs_to_idxs(const std::vec
1313
std::vector<size_t> idxs;
1414
idxs.reserve(regs.size());
1515
for (const auto& reg : regs) {
16-
OPENVINO_ASSERT(expected_type == snippets::RegType::undefined || reg.type == expected_type, "Reg type mismatch during to_idxs conversion");
16+
OPENVINO_ASSERT(reg.type == snippets::RegType::address ||
17+
expected_type == snippets::RegType::undefined || reg.type == expected_type,
18+
"Reg type mismatch during to_idxs conversion");
1719
idxs.emplace_back(reg.idx);
1820
}
1921
return idxs;

src/common/snippets/src/emitter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ std::ostream& operator<<(std::ostream& s, const Reg& r) {
3333
return "mask";
3434
case RegType::undefined:
3535
return "undefined";
36+
case RegType::address:
37+
return "address";
3638
default:
3739
OPENVINO_THROW("Unexpected RegType");
3840
}

src/common/snippets/src/lowered/pass/assign_registers.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
#include "snippets/lowered/pass/assign_registers.hpp"
66

7+
#include "snippets/itt.hpp"
78
#include "snippets/lowered/linear_ir.hpp"
9+
#include "snippets/op/kernel.hpp"
810
#include "snippets/snippets_isa.hpp"
9-
#include "snippets/itt.hpp"
1011
#include "snippets/utils/utils.hpp"
11-
#include "snippets/op/kernel.hpp"
12-
1312

1413
// This header is needed to avoid MSVC warning "C2039: 'inserter': is not a member of 'std'"
1514
#include <iterator>
@@ -21,9 +20,19 @@ namespace pass {
2120

2221
AssignRegisters::RegMap AssignRegisters::assign_regs_manually(const LinearIR& linear_ir, std::set<Reg>& gpr_pool, std::set<Reg>& vec_pool) {
2322
RegMap manually_assigned;
24-
OPENVINO_ASSERT(gpr_pool.size() >= (linear_ir.get_parameters().size() + linear_ir.get_results().size()),
23+
const auto internal_parameters = [&]() {
24+
std::vector<ExpressionPtr> internal_parameters;
25+
internal_parameters.reserve(linear_ir.get_parameters().size());
26+
for (const auto& param : linear_ir.get_parameters()) {
27+
if (!param->get_output_port_descriptor(0)->get_reg().is_address()) {
28+
internal_parameters.push_back(param);
29+
}
30+
}
31+
return internal_parameters;
32+
}();
33+
OPENVINO_ASSERT(gpr_pool.size() >= (internal_parameters.size() + linear_ir.get_results().size()),
2534
"Not enough gp registers in the pool to perform manual assignment");
26-
for (const auto& param : linear_ir.get_parameters()) {
35+
for (const auto& param : internal_parameters) {
2736
manually_assigned[param->get_output_port_descriptor(0)->get_reg()] = *gpr_pool.begin();
2837
gpr_pool.erase(gpr_pool.begin());
2938
}
@@ -179,10 +188,16 @@ bool AssignRegisters::run(LinearIR& linear_ir) {
179188
for (const auto& live_reg : expr->get_live_regs())
180189
mapped_live_regs.insert(assigned_reg_map[live_reg]);
181190
expr->set_live_regs(mapped_live_regs);
182-
for (const auto& in : expr->get_input_port_descriptors())
183-
in->set_reg(assigned_reg_map[in->get_reg()]);
184-
for (const auto& out : expr->get_output_port_descriptors())
185-
out->set_reg(assigned_reg_map[out->get_reg()]);
191+
for (const auto& in : expr->get_input_port_descriptors()) {
192+
if (!in->get_reg().is_address()) {
193+
in->set_reg(assigned_reg_map[in->get_reg()]);
194+
}
195+
}
196+
for (const auto& out : expr->get_output_port_descriptors()) {
197+
if (!out->get_reg().is_address()) {
198+
out->set_reg(assigned_reg_map[out->get_reg()]);
199+
}
200+
}
186201
}
187202
return false;
188203
}

src/common/snippets/src/lowered/pass/init_live_ranges.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
//
44

55
#include "snippets/lowered/pass/init_live_ranges.hpp"
6+
67
#include "snippets/itt.hpp"
7-
#include "snippets/op/subgraph.hpp"
88
#include "snippets/lowered/expressions/buffer_expression.hpp"
9+
#include "snippets/op/subgraph.hpp"
910

1011
namespace ov {
1112
namespace snippets {
@@ -17,9 +18,9 @@ inline bool pass_through_expr(const ExpressionPtr& expr) {
1718
const auto& node = expr->get_node();
1819
return op::Subgraph::is_shape_infer_op(node)
1920
#ifdef SNIPPETS_DEBUG_CAPS
20-
|| ov::is_type_any_of<op::PerfCountBeginBase, op::PerfCountEndBase>(node)
21+
|| ov::is_type_any_of<op::PerfCountBeginBase, op::PerfCountEndBase>(node)
2122
#endif
22-
|| ov::is_type<BufferExpression>(expr);
23+
|| ov::is_type<BufferExpression>(expr);
2324
}
2425

2526
} // namespace

src/common/snippets/src/lowered/port_descriptor.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ void PortDescriptor::set_subtensor(const VectorDims& subtensor) {
6666
m_subtensor_shape = subtensor;
6767
}
6868

69+
void PortDescriptor::set_reg(Reg reg) {
70+
OPENVINO_ASSERT(m_reg.type != RegType::address, "Failed to set reg: reg with 'address' type mustn't be changed");
71+
m_reg = std::move(reg);
72+
}
73+
74+
void PortDescriptor::set_reg_type(RegType type) {
75+
OPENVINO_ASSERT(m_reg.type != RegType::address, "Failed to set reg type: address reg type mustn't be changed");
76+
m_reg.type = type;
77+
}
78+
6979
void PortDescriptor::set_subtensor_dim(size_t idx, VectorDims::value_type value) {
7080
OPENVINO_ASSERT(idx < m_subtensor_shape.size(), "Failed to set subtensor value: idx should be less than size");
7181
*(m_subtensor_shape.rbegin() + idx) = value;
@@ -202,6 +212,18 @@ PortDescriptorPtr PortDescriptorUtils::get_port_descriptor_ptr(const Output<cons
202212
return out_descs[out.get_index()];
203213
}
204214

215+
void PortDescriptorUtils::set_address_reg_type(const ov::Input<ov::Node>& in) {
216+
auto desc = get_port_descriptor_ptr(in);
217+
desc->set_reg_type(RegType::address);
218+
set_port_descriptor_ptr(in, desc);
219+
}
220+
221+
void PortDescriptorUtils::set_address_reg_type(const ov::Output<ov::Node>& out) {
222+
auto desc = get_port_descriptor_ptr(out);
223+
desc->set_reg_type(RegType::address);
224+
set_port_descriptor_ptr(out, desc);
225+
}
226+
205227
void PortDescriptorUtils::clean(const std::shared_ptr<ov::Node>& node) {
206228
auto& rt_info = node->get_rt_info();
207229
rt_info.erase(PortDescriptorVectorAttribute::get_type_info_static());

src/common/snippets/src/pass/mlp_seq_tokenization.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,20 @@ inline bool has_one_consumer(const std::shared_ptr<ov::Node>& node) {
2727
}
2828

2929
size_t get_potential_body_params(const std::shared_ptr<ov::Node>& op) {
30+
if (const auto fq = ov::as_type_ptr<ov::op::v0::FakeQuantize>(op)) {
31+
return ov::snippets::utils::get_non_scalar_constant_count_for_fq(fq);
32+
}
3033
size_t count = 0;
3134
for (size_t i = 1; i < op->get_input_size(); ++i) {
3235
const auto input = op->input_value(i);
3336
const auto parent = input.get_node_shared_ptr();
3437
const auto constant = ov::as_type_ptr<ov::op::v0::Constant>(parent);
3538
const auto is_scalar = constant && (ov::shape_size(input.get_shape()) == 1);
3639
const auto should_be_inside_body = constant && ov::snippets::op::Subgraph::constant_input_should_be_inside_body(op);
37-
const auto is_fq_weight = constant && ov::is_type<ov::op::v0::FakeQuantize>(op);
38-
if (!(is_scalar || should_be_inside_body || is_fq_weight)) {
40+
if (!(is_scalar || should_be_inside_body)) {
3941
count++;
4042
}
4143
}
42-
if (const auto fq = ov::as_type_ptr<ov::op::v0::FakeQuantize>(op)) {
43-
count += ov::snippets::utils::get_non_scalar_constant_count_for_fq(fq);
44-
}
4544
return count;
4645
}
4746

@@ -150,14 +149,26 @@ TokenizeMLPSeqSnippets::TokenizeMLPSeqSnippets(const SnippetsTokenization::Confi
150149
auto interm_op = prev_op->get_output_target_inputs(0).begin()->get_node()->shared_from_this();
151150
auto available_regs = config.get_data_ptr_gpr_count();
152151

152+
bool postops_fusion_possible = true;
153+
std::shared_ptr<ov::op::v0::MatMul> cur_matmul = matmul0;
153154
while (has_one_consumer(prev_op)) {
154155
auto current_potential_body_params_count = potential_body_params_count;
155156

156157
if (is_matmul_supported(interm_op) && !transformation_callback(interm_op)) {
157158
// +1 for weights
158159
current_potential_body_params_count++;
160+
// If MatMul is the first in the sequence, postops fusion status is reset
161+
postops_fusion_possible = true;
162+
cur_matmul = ov::as_type_ptr<ov::op::v0::MatMul>(interm_op);
163+
OPENVINO_ASSERT(cur_matmul, "MatMul is expected");
159164
} else if (is_supported_intermediate_op(interm_op)) {
160-
current_potential_body_params_count += get_potential_body_params(interm_op);
165+
// Intermediate op contributes to the body params count only if can't be fused as post-op
166+
// or if a previous node between MatMul and this op is not supported by post-op fusion
167+
if (!postops_fusion_possible || config.get_can_be_fused_as_postop() == nullptr ||
168+
!config.get_can_be_fused_as_postop()(cur_matmul, interm_op)) {
169+
postops_fusion_possible = false;
170+
current_potential_body_params_count += get_potential_body_params(interm_op);
171+
}
161172
} else {
162173
// Unsupported op
163174
break;
@@ -190,7 +201,6 @@ TokenizeMLPSeqSnippets::TokenizeMLPSeqSnippets(const SnippetsTokenization::Confi
190201

191202
// mark the Subgraph as Completed to not allow Snippets to include any nodes into this Subgraph in common Tokenization
192203
SetSnippetsSubgraphType(subgraph, SnippetsSubgraphType::Completed);
193-
194204
return true;
195205
});
196206
}

src/common/snippets/src/pass/propagate_precision.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "openvino/core/rt_info.hpp"
1111
#include "transformations/utils/utils.hpp"
1212

13-
#include <assert.h>
1413
#include <memory>
1514

1615

@@ -65,12 +64,12 @@ bool ov::snippets::pass::PropagatePrecision::run_on_model(const std::shared_ptr<
6564
input_precisions.push_back(input_precision);
6665
}
6766

68-
assert(std::all_of(
69-
supported_precisions.begin(),
70-
supported_precisions.end(),
71-
[&input_precisions](const std::vector<element::Type>& precisions) {
72-
return precisions.size() == input_precisions.size();
73-
}) && "input precisions count is not equal for supported precisions");
67+
OPENVINO_ASSERT(std::all_of(supported_precisions.begin(),
68+
supported_precisions.end(),
69+
[&input_precisions](const std::vector<element::Type>& precisions) {
70+
return precisions.size() == input_precisions.size();
71+
}),
72+
"input precisions count is not equal for supported precisions");
7473

7574
// update input precisions
7675
// if possible then convert precisions to supported

src/common/snippets/src/shape_inference/shape_infer_instances.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ Result HorizonOpShapeInfer::infer(const std::vector<VectorDimsRef>& input_shapes
152152
}
153153

154154
BrgemmShapeInfer::BrgemmShapeInfer(const std::shared_ptr<Node>& n) {
155-
for (const auto& in : n->inputs()) {
155+
// Only first 2 inputs are used for shape inference
156+
for (size_t i = 0; i < 2; ++i) {
157+
const auto& in = n->input(i);
156158
const auto& port = lowered::PortDescriptorUtils::get_port_descriptor_ptr(in);
157159
m_io_layouts.push_back(port->get_layout());
158160
}
@@ -161,7 +163,7 @@ BrgemmShapeInfer::BrgemmShapeInfer(const std::shared_ptr<Node>& n) {
161163
}
162164

163165
Result BrgemmShapeInfer::infer(const std::vector<VectorDimsRef>& input_shapes) {
164-
OPENVINO_ASSERT(input_shapes.size() == 2 || input_shapes.size() == 3, "BRGEMM expects 2 or 3 input shapes for shape inference");
166+
OPENVINO_ASSERT(input_shapes.size() >= 2, "Unexpected input_shapes count");
165167

166168
// Todo: Ideally we should use the layout stored in PortDescriptors. Can we do it?
167169
const auto& arg0_shape = ov::snippets::utils::get_planar_vdims(input_shapes[0].get(), m_io_layouts[0]);

0 commit comments

Comments
 (0)