GRUCellFusion - fix handling bias in rz order (#17651)
Currently GRUCellFusion treats bias as if it's always in zr order, which sometimes is not the case. So whenever GRUCellFusion detects rz order, it should also split bias into r and z and concat the halves into zr. Ticket: CVS-97025
This commit is contained in:
1 parent
c5f4406c34
commit
48f207f961
3 files changed
+31
-29
No files matched your search
+19
-17
@@ -120,32 +120,34 @@ ov::pass::GRUCellFusion::GRUCellFusion() {
|
||||
auto cnt_of_consumers_of_zero_out = pattern_split->get_output_target_inputs(0).size();
|
||||
auto cnt_of_consumers_of_first_out = pattern_split->get_output_target_inputs(1).size();
|
||||
|
||||
Output<Node> Wzrh, Rzrh;
|
||||
Output<Node> B;
|
||||
if (pattern_map.find(add_1) != pattern_map.end()) {
|
||||
B = pattern_map[add_1]->input_value(1);
|
||||
} else {
|
||||
B = rg.make<Constant>(WR.get_element_type(), Shape{1, static_cast<size_t>(2 * hidden_size)}, 0);
|
||||
}
|
||||
|
||||
Output<Node> Bh;
|
||||
if (pattern_map.find(add_2) != pattern_map.end()) {
|
||||
Bh = pattern_map[add_2]->input_value(1);
|
||||
} else {
|
||||
Bh = rg.make<Constant>(WRh.get_element_type(), Shape{1, static_cast<size_t>(hidden_size)}, 0);
|
||||
}
|
||||
|
||||
Output<Node> Wzrh, Rzrh, Bzrh;
|
||||
if (cnt_of_consumers_of_zero_out == 1 && cnt_of_consumers_of_first_out == 2) {
|
||||
tie(Wzrh, Rzrh) = process_weights(rg, false, WR, WRh, input_size, hidden_size, axis_0, axis_1);
|
||||
auto split_B_r_z = rg.make<Split>(B, axis_1, 2);
|
||||
Bzrh = rg.make<Concat>(OutputVector{split_B_r_z->output(1), split_B_r_z->output(0), Bh}, 1);
|
||||
} else if (cnt_of_consumers_of_zero_out == 2 && cnt_of_consumers_of_first_out == 1) {
|
||||
tie(Wzrh, Rzrh) = process_weights(rg, true, WR, WRh, input_size, hidden_size, axis_0, axis_1);
|
||||
Bzrh = rg.make<Concat>(OutputVector{B, Bh}, 1);
|
||||
} else {
|
||||
// we can't detect the weights format
|
||||
return false;
|
||||
}
|
||||
|
||||
Output<Node> bias_add_1;
|
||||
if (pattern_map.find(add_1) != pattern_map.end()) {
|
||||
bias_add_1 = pattern_map[add_1]->input_value(1);
|
||||
} else {
|
||||
bias_add_1 = rg.make<Constant>(WR.get_element_type(), Shape{1, static_cast<size_t>(2 * hidden_size)}, 0);
|
||||
}
|
||||
|
||||
Output<Node> bias_add_2;
|
||||
if (pattern_map.find(add_2) != pattern_map.end()) {
|
||||
bias_add_2 = pattern_map[add_2]->input_value(1);
|
||||
} else {
|
||||
bias_add_2 = rg.make<Constant>(WRh.get_element_type(), Shape{1, static_cast<size_t>(hidden_size)}, 0);
|
||||
}
|
||||
|
||||
auto B = rg.make<Concat>(OutputVector{bias_add_1, bias_add_2}, 1);
|
||||
auto squeeze_B = rg.make<Squeeze>(B, axis_0);
|
||||
auto squeeze_B = rg.make<Squeeze>(Bzrh, axis_0);
|
||||
|
||||
string act_name_1 = pattern_map.at(activation_1)->get_type_name();
|
||||
string act_name_2 = pattern_map.at(activation_2)->get_type_name();
|
||||
|
||||
@@ -96,10 +96,10 @@ shared_ptr<Model> gen_reference(WeightsFormat format,
|
||||
auto WRh = make_shared<Parameter>(f32, Shape{hidden_size, input_size + hidden_size});
|
||||
ParameterVector params = {X, H, WR, WRh};
|
||||
|
||||
shared_ptr<Node> Bzr = make_shared<Constant>(f32, Shape{1, 2 * hidden_size}, 0);
|
||||
shared_ptr<Node> B = make_shared<Constant>(f32, Shape{1, 2 * hidden_size}, 0);
|
||||
if (use_bias_add_1) {
|
||||
Bzr = make_shared<Parameter>(f32, Shape{1, 2 * hidden_size});
|
||||
params.push_back(dynamic_pointer_cast<Parameter>(Bzr));
|
||||
B = make_shared<Parameter>(f32, Shape{1, 2 * hidden_size});
|
||||
params.push_back(dynamic_pointer_cast<Parameter>(B));
|
||||
}
|
||||
shared_ptr<Node> Bh = make_shared<Constant>(f32, Shape{1, hidden_size}, 0);
|
||||
if (use_bias_add_2) {
|
||||
@@ -112,11 +112,12 @@ shared_ptr<Model> gen_reference(WeightsFormat format,
|
||||
auto split_lenghts = make_shared<Constant>(i64, Shape{2}, vector<size_t>{input_size, hidden_size});
|
||||
auto split_WRh = make_shared<VariadicSplit>(WRh, axis_1, split_lenghts);
|
||||
|
||||
Output<Node> Wzrh, Rzrh;
|
||||
Output<Node> Wzrh, Rzrh, Bzrh;
|
||||
if (format == WeightsFormat::zr) {
|
||||
auto split_WRzr = make_shared<VariadicSplit>(WR, axis_1, split_lenghts);
|
||||
Wzrh = make_shared<Concat>(OutputVector{split_WRzr->output(0), split_WRh->output(0)}, 0);
|
||||
Rzrh = make_shared<Concat>(OutputVector{split_WRzr->output(1), split_WRh->output(1)}, 0);
|
||||
Bzrh = make_shared<Concat>(OutputVector{B, Bh}, 1);
|
||||
} else {
|
||||
auto split_WRrz = make_shared<VariadicSplit>(WR, axis_1, split_lenghts);
|
||||
auto split_W_r_z = make_shared<Split>(split_WRrz->output(0), axis_0, 2);
|
||||
@@ -125,10 +126,11 @@ shared_ptr<Model> gen_reference(WeightsFormat format,
|
||||
make_shared<Concat>(OutputVector{split_W_r_z->output(1), split_W_r_z->output(0), split_WRh->output(0)}, 0);
|
||||
Rzrh =
|
||||
make_shared<Concat>(OutputVector{split_R_r_z->output(1), split_R_r_z->output(0), split_WRh->output(1)}, 0);
|
||||
auto split_B_r_z = make_shared<Split>(B, axis_1, 2);
|
||||
Bzrh = make_shared<Concat>(OutputVector{split_B_r_z->output(1), split_B_r_z->output(0), Bh}, 1);
|
||||
}
|
||||
auto B = make_shared<Concat>(OutputVector{Bzr, Bh}, 1);
|
||||
|
||||
auto squeeze_B = make_shared<Squeeze>(B, axis_0);
|
||||
auto squeeze_B = make_shared<Squeeze>(Bzrh, axis_0);
|
||||
auto cell =
|
||||
make_shared<GRUCell>(X, H, Wzrh, Rzrh, squeeze_B, hidden_size, vector<string>{activation_1, activation_2});
|
||||
return make_shared<Model>(OutputVector{cell}, params);
|
||||
@@ -201,13 +203,13 @@ static const vector<GRUFusionParams> params = {
|
||||
GRUFusionParams{WeightsFormat::zr, "tanh", "sigmoid", 2, 128, 32, true, true},
|
||||
GRUFusionParams{WeightsFormat::zr, "tanh", "tanh", 2, 128, 32, true, false},
|
||||
GRUFusionParams{WeightsFormat::zr, "sigmoid", "relu", 2, 128, 32, false, false},
|
||||
GRUFusionParams{WeightsFormat::zr, "relu", "tanh", 2, 128, 32, false, true},
|
||||
GRUFusionParams{WeightsFormat::rz, "sigmoid", "tanh", 1, 1, 1, true, true},
|
||||
GRUFusionParams{WeightsFormat::rz, "tanh", "sigmoid", 2, 128, 32, true, true},
|
||||
GRUFusionParams{WeightsFormat::rz, "relu", "sigmoid", 2, 128, 32, true, true},
|
||||
GRUFusionParams{WeightsFormat::rz, "tanh", "tanh", 2, 128, 32, true, false},
|
||||
GRUFusionParams{WeightsFormat::rz, "sigmoid", "relu", 2, 128, 32, false, false},
|
||||
// 92424: accuracy issue, it looks like the test infrastructure issue, the graphs are the same.
|
||||
// GRUFusionParams{WeightsFormat::zr, "relu", "tanh", 2, 128, 32, false, true},
|
||||
// GRUFusionParams{WeightsFormat::rz, "relu", "tanh", 2, 128, 32, false, true},
|
||||
GRUFusionParams{WeightsFormat::rz, "relu", "tanh", 2, 128, 32, false, true},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(GRUFusionTest, GRUFusionTest, ValuesIn(params));
|
||||
|
||||
@@ -1039,9 +1039,7 @@ AccuracyCheckResult accuracy_check(const std::shared_ptr<ov::Model>& ref_functio
|
||||
IE_ASSERT(ref_outputs.size() == outputs.size());
|
||||
|
||||
for (int i = 0; i < ref_outputs.size(); i++) {
|
||||
ov::test::utils::compare(ref_outputs[i], outputs[i],
|
||||
std::numeric_limits<double>::max(),
|
||||
std::numeric_limits<double>::max());
|
||||
ov::test::utils::compare(ref_outputs[i], outputs[i], 5e-4, 1e-3);
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error &re) {
|
||||
|
||||
Reference in new issue
Block a user