Revert "More accurate shape of optimization" (#24941)
Reverts openvinotoolkit/openvino#24845 Issue CVS-143648
This commit is contained in:
parent
6e2286086f
commit
395d6b7e09
|
|
@ -555,7 +555,7 @@ ov::pass::RoPEFusionQwen::RoPEFusionQwen(int split_output_id) {
|
|||
{{"special_zero", true}});
|
||||
auto slice_Slice_543 = GenSlice(view_Reshape_424, 0, head_size, 1, 3); // tensor_array<f32[?,?,32,128]>
|
||||
|
||||
auto hidden_states = makePattern(); //
|
||||
auto hidden_states = makePattern("f32[?,?,?]"); //
|
||||
auto ShapeOf_485735 = makePattern<opset1::ShapeOf>({hidden_states}, {});
|
||||
auto Multiply_567524 = makePattern<opset1::Multiply>({ShapeOf_485735, {-1}}, {{"auto_broadcast", "numpy"}});
|
||||
auto Gather_377635 = makePattern<opset8::Gather>({Multiply_567524, {1}, 0}, {{"batch_dims", 0}});
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#include "openvino/op/shape_of.hpp"
|
||||
#include "openvino/op/squeeze.hpp"
|
||||
#include "openvino/op/util/multi_subgraph_base.hpp"
|
||||
#include "openvino/op/util/op_types.hpp"
|
||||
#include "transformations/utils/utils.hpp"
|
||||
|
||||
namespace {
|
||||
|
|
@ -223,101 +222,7 @@ void optimize_value_usage(ov::Output<ov::Node>& output, STS_map& symbol_shape_so
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<ov::Node>> topological_order(const std::shared_ptr<ov::Model>& m) {
|
||||
auto order = m->get_ordered_ops();
|
||||
|
||||
// step 1: split model into parameter related and parameter non-related ops
|
||||
const std::string op_depends_on_parameter = "topological_sort_op_depends_on";
|
||||
// values: true - parameter dependent; false otherwise
|
||||
for (const auto& op : order) {
|
||||
if (ov::as_type_ptr<ov::op::v0::Parameter>(op)) {
|
||||
op->get_rt_info()[op_depends_on_parameter] = true;
|
||||
} else if (ov::as_type_ptr<ov::op::v0::Constant>(op) || ov::as_type_ptr<ov::op::v0::ShapeOf>(op) ||
|
||||
ov::as_type_ptr<ov::op::v3::ShapeOf>(op) ||
|
||||
std::dynamic_pointer_cast<ov::op::util::VariableExtension>(op)) {
|
||||
op->get_rt_info()[op_depends_on_parameter] = false;
|
||||
} else { // deduce op type from inputs
|
||||
const auto& inputs = op->input_values();
|
||||
op->get_rt_info()[op_depends_on_parameter] =
|
||||
std::any_of(inputs.begin(),
|
||||
inputs.end(),
|
||||
[&op_depends_on_parameter](const ov::Output<ov::Node>& input) {
|
||||
return input.get_node_shared_ptr()->get_rt_info()[op_depends_on_parameter].as<bool>();
|
||||
});
|
||||
}
|
||||
}
|
||||
// step 2: starting from Result -- assign weight to ops:
|
||||
// if parameter dependant, weights is maximum of output indices plus one
|
||||
// else weights is maximum of output indices
|
||||
// this step doesn't assign weights to all the ops, this is intentional and will be used in the following step
|
||||
const std::string weight_rt_info_name = "topological_sort_weight";
|
||||
for (auto it = order.rbegin(); it != order.rend(); ++it) {
|
||||
const auto& op = *it;
|
||||
int64_t weight = 0;
|
||||
if (ov::as_type_ptr<ov::op::v0::Result>(op)) {
|
||||
op->get_rt_info()[weight_rt_info_name] = weight;
|
||||
} else {
|
||||
bool output_has_weight = false;
|
||||
for (const auto& output : op->outputs()) {
|
||||
for (const auto& input : output.get_target_inputs()) {
|
||||
const auto& output_op = input.get_node();
|
||||
const auto& rt_info = output_op->get_rt_info();
|
||||
if (!rt_info.count(weight_rt_info_name))
|
||||
continue;
|
||||
output_has_weight = true;
|
||||
auto output_weight = rt_info.at(weight_rt_info_name).as<int64_t>();
|
||||
weight = output_weight > weight ? output_weight : weight;
|
||||
}
|
||||
}
|
||||
if (output_has_weight) {
|
||||
if (op->get_rt_info()[op_depends_on_parameter].as<bool>()) {
|
||||
weight += 1;
|
||||
}
|
||||
op->get_rt_info()[weight_rt_info_name] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
// step 3: make propagation for all the nodes:
|
||||
// if weight is already assigned -- skip operation
|
||||
// else operation weights is minimum of input indices
|
||||
// if all operation inputs have no weights -- this op is isolated and this algorithm doesn't make sense,
|
||||
// such cases are extremely rare and rather theoretical, to handle them we return original ov::Model op order
|
||||
std::map<int64_t, std::vector<std::shared_ptr<ov::Node>>> level_to_vector;
|
||||
for (const auto& op : order) {
|
||||
if (!op->get_rt_info().count(weight_rt_info_name)) {
|
||||
int64_t weight = std::numeric_limits<int64_t>::max();
|
||||
for (const auto& input : op->input_values()) {
|
||||
const auto& rt_info = input.get_node_shared_ptr()->get_rt_info();
|
||||
if (!rt_info.count(weight_rt_info_name))
|
||||
continue;
|
||||
auto input_weight = rt_info.at(weight_rt_info_name).as<int64_t>();
|
||||
weight = input_weight < weight ? input_weight : weight;
|
||||
}
|
||||
if (weight != std::numeric_limits<int64_t>::max())
|
||||
op->get_rt_info()[weight_rt_info_name] = weight;
|
||||
else
|
||||
return m->get_ordered_ops();
|
||||
}
|
||||
level_to_vector[op->get_rt_info().at(weight_rt_info_name).as<int64_t>()].push_back(op);
|
||||
}
|
||||
// finalization: descending order for levels and ops within level are ordered by get_ordered_ops
|
||||
std::vector<std::shared_ptr<ov::Node>> result;
|
||||
result.reserve(order.size());
|
||||
for (auto it = level_to_vector.rbegin(); it != level_to_vector.rend(); ++it) {
|
||||
const auto& item = *it;
|
||||
result.insert(result.end(), item.second.begin(), item.second.end());
|
||||
for (const auto& op : item.second) {
|
||||
op->get_rt_info().erase(weight_rt_info_name);
|
||||
op->get_rt_info().erase(op_depends_on_parameter);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void save_shape_sources(const std::shared_ptr<ov::Node>& op, STS_map& symbol_shape_source) {
|
||||
if (!ov::is_type<ov::op::v0::ShapeOf>(op) && !ov::is_type<ov::op::v3::ShapeOf>(op))
|
||||
return;
|
||||
const auto& output = op->input_value(0);
|
||||
void save_shape_sources(const ov::Output<ov::Node>& output, STS_map& symbol_shape_source) {
|
||||
for (const auto& d : output.get_partial_shape()) {
|
||||
if (d.is_static())
|
||||
continue;
|
||||
|
|
@ -335,7 +240,7 @@ bool ov::pass::OptimizeSymbolsUsedAsValues::run_on_model(const std::shared_ptr<o
|
|||
RUN_ON_FUNCTION_SCOPE(OptimizeSymbolsUsedAsValues);
|
||||
STS_map symbol_shape_source;
|
||||
STS_map symbol_value_source;
|
||||
for (const auto& op : topological_order(m)) {
|
||||
for (const auto& op : m->get_ordered_ops()) {
|
||||
// Result has output port which has shared (during validate_and_infer_type) tensor with input port.
|
||||
// Transformations may replace input of Result. After replacement and before Result::validate_and_infer_type --
|
||||
// output tensor of Result may contain inaccurate shape / symbols due to the sharing with tensor which may be
|
||||
|
|
@ -347,9 +252,10 @@ bool ov::pass::OptimizeSymbolsUsedAsValues::run_on_model(const std::shared_ptr<o
|
|||
// LTS maps aren't shared with sub-graphs because inner graph can not access outer graph for label sources
|
||||
ov::op::util::process_subgraph(*this, op);
|
||||
|
||||
for (auto& output : op->outputs())
|
||||
for (auto& output : op->outputs()) {
|
||||
optimize_value_usage(output, symbol_shape_source, symbol_value_source);
|
||||
save_shape_sources(op, symbol_shape_source);
|
||||
save_shape_sources(output, symbol_shape_source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,16 +75,22 @@ TEST_F(TransformationTestsF, ApplySymbolEquivalence_Concat_Values) {
|
|||
auto input_2 = make_shared<v0::Parameter>(element::f32, PartialShape::dynamic(4));
|
||||
auto concat = make_shared<v0::Concat>(OutputVector{input_1, input_2}, -1);
|
||||
|
||||
auto shape = make_shared<v3::ShapeOf>(concat);
|
||||
auto gather = make_shared<v8::Gather>(shape,
|
||||
v0::Constant::create(element::i64, {1}, {-1}),
|
||||
v0::Constant::create(element::i64, {}, {0}));
|
||||
auto shape_1 = make_shared<v3::ShapeOf>(input_1);
|
||||
auto gather_1 = make_shared<v8::Gather>(shape_1,
|
||||
v0::Constant::create(element::i64, {1}, {3}),
|
||||
v0::Constant::create(element::i64, {}, {0}));
|
||||
|
||||
auto shape_2 = make_shared<v3::ShapeOf>(input_2);
|
||||
auto gather_2 = make_shared<v8::Gather>(shape_2,
|
||||
v0::Constant::create(element::i64, {1}, {3}),
|
||||
v0::Constant::create(element::i64, {}, {0}));
|
||||
|
||||
auto sum = make_shared<v1::Add>(gather_1, gather_2);
|
||||
|
||||
auto reshape = make_shared<v1::Reshape>(
|
||||
concat,
|
||||
make_shared<v0::Concat>(OutputVector{gather, v0::Constant::create(element::i64, {1}, {-1})}, 0),
|
||||
make_shared<v0::Concat>(OutputVector{sum, v0::Constant::create(element::i64, {1}, {-1})}, 0),
|
||||
false);
|
||||
|
||||
model_ref = make_shared<Model>(NodeVector{reshape}, ParameterVector{input_2, input_1});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue