[CONFORMANCE] Enabling SubgraphsDumping (#18896)
* Change fused_names algo -> cut subgraphs * Added extractor name to serialization dir + meta_info * Uncomment log * Add this_op_cnt to model_info, fix in_info for model * Replace clone node second time to relace input node * fix small problem * small fixes * Switch off repeat extractor * remove model serialization * fused_names * change default device in fused_names extractor * fused_names * Small speed up * Move replace of const by param to cache * Move alignament of in_info to extractorManager * Sort model by size (check mem fragmentation) * Fix problem with opset12 * Update manager.cpp * Serialize cache in case of long * Add test * Update graph_cache.cpp * Update graph_cache.cpp * Graph cache size * test other approach * remove extra * Fix issue with replae * try with 1gb limitatiom * to merge * revert
This commit is contained in:
parent
cde0893271
commit
d2594200bc
@ -19,7 +19,7 @@ class GraphCache : public ICache {
|
||||
public:
|
||||
void update_cache(const std::shared_ptr<ov::Model>& model,
|
||||
const std::string& model_meta_data,
|
||||
bool extract_body = true) override;
|
||||
bool extract_body) override;
|
||||
void serialize_cache() override;
|
||||
|
||||
static std::shared_ptr<GraphCache>& get() {
|
||||
@ -35,6 +35,7 @@ public:
|
||||
}
|
||||
|
||||
void reset_cache() override {
|
||||
m_graph_cache.clear();
|
||||
reset();
|
||||
};
|
||||
|
||||
@ -42,17 +43,21 @@ protected:
|
||||
std::map<std::shared_ptr<ov::Model>, MetaInfo> m_graph_cache;
|
||||
ExtractorsManager m_manager = ExtractorsManager();
|
||||
static std::shared_ptr<GraphCache> m_cache_instance;
|
||||
// cache byte size
|
||||
size_t m_graph_cache_bytesize = 0;
|
||||
|
||||
GraphCache() {
|
||||
ExtractorsManager::ExtractorsMap matchers = {
|
||||
{ "fused_names", FusedNamesExtractor::Ptr(new FusedNamesExtractor) },
|
||||
{ "repeat_pattern", RepeatPatternExtractor::Ptr(new RepeatPatternExtractor) },
|
||||
// temporary disabling according mem leaks in CI and not using swap mem
|
||||
// { "fused_names", FusedNamesExtractor::Ptr(new FusedNamesExtractor) },
|
||||
// { "repeat_pattern", RepeatPatternExtractor::Ptr(new RepeatPatternExtractor) },
|
||||
};
|
||||
m_manager.set_extractors(matchers);
|
||||
}
|
||||
|
||||
void update_cache(const std::shared_ptr<ov::Model>& model, const std::string& model_path,
|
||||
const std::map<std::string, InputInfo>& input_info, size_t model_op_cnt);
|
||||
std::map<std::string, InputInfo>& input_info, const std::string& extractor_name,
|
||||
size_t model_op_cnt);
|
||||
};
|
||||
|
||||
} // namespace subgraph_dumper
|
||||
|
@ -52,7 +52,8 @@ struct InputInfo {
|
||||
}
|
||||
};
|
||||
|
||||
using ExtractedPattern = std::pair<std::shared_ptr<ov::Model>, std::map<std::string, InputInfo>>;
|
||||
// ov_model, input_info, extractor_name
|
||||
using ExtractedPattern = std::tuple<std::shared_ptr<ov::Model>, std::map<std::string, InputInfo>, std::string>;
|
||||
|
||||
} // namespace subgraph_dumper
|
||||
} // namespace tools
|
||||
|
@ -13,18 +13,30 @@ namespace subgraph_dumper {
|
||||
|
||||
class MetaInfo {
|
||||
public:
|
||||
MetaInfo(const std::string& model_path = "", const std::map<std::string, InputInfo>& _input_info = {}, size_t total_op_cnt = 1, size_t model_priority = 1);
|
||||
MetaInfo(const std::string& model_path = "", const std::map<std::string, InputInfo>& _input_info = {},
|
||||
size_t total_op_cnt = 1, size_t this_op_cnt = 1, const std::string& extractor = "", size_t model_priority = 1);
|
||||
MetaInfo(std::map<std::string, InputInfo> _in_info,
|
||||
std::map<std::string, ModelInfo> _model_info,
|
||||
std::unordered_set<std::string> _extractors) :
|
||||
model_info(_model_info),
|
||||
input_info(_in_info),
|
||||
extractors(_extractors) {};
|
||||
void serialize(const std::string& serialization_path);
|
||||
void update(const std::string& model_path, const std::map<std::string, InputInfo>& _input_info,
|
||||
size_t _total_op_cnt = 1, const std::vector<std::string>& ignored_inputs = {});
|
||||
std::map<std::string, InputInfo> get_input_info();
|
||||
std::map<std::string, ModelInfo> get_model_info();
|
||||
void update(const std::string& model_path, const std::map<std::string, InputInfo>& _input_info, size_t _total_op_cnt = 1,
|
||||
size_t _this_op_cnt = 1, const std::string& extractor = "", const std::vector<std::string>& ignored_inputs = {});
|
||||
std::map<std::string, InputInfo> get_input_info() const;
|
||||
std::map<std::string, ModelInfo> get_model_info() const;
|
||||
std::string get_any_extractor() const { return *extractors.begin(); }
|
||||
|
||||
static MetaInfo read_meta_from_file(const std::string& meta_path);
|
||||
|
||||
protected:
|
||||
// { input_node_name: input_info }
|
||||
std::map<std::string, InputInfo> input_info;
|
||||
// { model_name: model_paths, this_op/graph_cnt, total_op_cnt, model_priority}
|
||||
std::map<std::string, ModelInfo> model_info;
|
||||
// { extractors }
|
||||
std::unordered_set<std::string> extractors;
|
||||
|
||||
// to store model priority ranges to normilize graph_priority
|
||||
static unsigned long MAX_MODEL_PRIORITY;
|
||||
|
@ -15,9 +15,10 @@ struct ModelInfo {
|
||||
std::set<std::string> model_paths;
|
||||
size_t this_op_cnt, total_op_cnt, model_priority;
|
||||
|
||||
ModelInfo(const std::string& model_path = "", size_t total_ops_in_model = 1, size_t _model_priority = 1) :
|
||||
total_op_cnt(total_ops_in_model), model_paths({model_path}),
|
||||
this_op_cnt(1), model_priority(_model_priority) {}
|
||||
ModelInfo(const std::string& model_path = "", size_t total_ops_in_model = 1, size_t this_ops_in_model = 1, size_t _model_priority = 1) :
|
||||
total_op_cnt(total_ops_in_model), this_op_cnt(this_ops_in_model), model_priority(_model_priority) {
|
||||
model_paths = model_path.empty() ? std::set<std::string>() : std::set<std::string>({ model_path }) ;
|
||||
}
|
||||
|
||||
bool operator==(const ModelInfo& model_info_ref) const {
|
||||
if (this->model_priority != model_info_ref.model_priority || this->this_op_cnt != model_info_ref.this_op_cnt ||
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
}
|
||||
|
||||
void reset_cache() override {
|
||||
m_ops_cache.clear();
|
||||
reset();
|
||||
};
|
||||
|
||||
|
@ -14,11 +14,16 @@ namespace subgraph_dumper {
|
||||
|
||||
class FusedNamesExtractor : public SubgraphExtractor {
|
||||
public:
|
||||
FusedNamesExtractor();
|
||||
std::list<ExtractedPattern> extract(const std::shared_ptr<ov::Model> &model,
|
||||
bool is_extract_body = true) override;
|
||||
void set_target_device(const std::string& _device) { device = _device; }
|
||||
|
||||
protected:
|
||||
std::unordered_set<std::string> extract_compiled_model_names(const std::shared_ptr<ov::Model>& model);
|
||||
|
||||
std::string device;
|
||||
std::shared_ptr<ov::Core> core;
|
||||
};
|
||||
|
||||
} // namespace subgraph_dumper
|
||||
|
@ -16,15 +16,25 @@ public:
|
||||
explicit ExtractorsManager(const ExtractorsMap& extractors = {}) : m_extractors(extractors) {}
|
||||
|
||||
bool match(const std::shared_ptr<ov::Model> &model,
|
||||
const std::shared_ptr<ov::Model> &ref);
|
||||
const std::shared_ptr<ov::Model> &ref,
|
||||
std::map<std::string, InputInfo> &in_info,
|
||||
const std::map<std::string, InputInfo> &in_info_ref);
|
||||
std::list<ExtractedPattern> extract(const std::shared_ptr<ov::Model> &model,
|
||||
bool is_extract_body = true);
|
||||
|
||||
void set_extractors(const ExtractorsMap& extractors = {}) { m_extractors = extractors; }
|
||||
ExtractorsMap get_extractors() { return m_extractors; }
|
||||
|
||||
std::map<std::string, InputInfo> align_input_info(const std::shared_ptr<ov::Model>& model,
|
||||
const std::shared_ptr<ov::Model>& model_ref,
|
||||
const std::map<std::string, InputInfo> &in_info,
|
||||
const std::map<std::string, InputInfo> &in_info_ref);
|
||||
|
||||
protected:
|
||||
ExtractorsMap m_extractors = {};
|
||||
|
||||
bool match(const std::shared_ptr<ov::Model> &model,
|
||||
const std::shared_ptr<ov::Model> &ref);
|
||||
};
|
||||
|
||||
} // namespace subgraph_dumper
|
||||
|
@ -26,7 +26,10 @@ public:
|
||||
return std::list<ExtractedPattern>{};
|
||||
};
|
||||
|
||||
void set_extractor_name(const std::string& _extractor_name) { extractor_name = _extractor_name; }
|
||||
|
||||
protected:
|
||||
std::string extractor_name = "";
|
||||
FunctionsComparator comparator = FunctionsComparator::no_default()
|
||||
.enable(FunctionsComparator::ATTRIBUTES)
|
||||
.enable(FunctionsComparator::NODES)
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#include "openvino/util/file_util.hpp"
|
||||
|
||||
@ -56,7 +58,8 @@ static std::map<ModelCacheStatus, std::string> model_cache_status_to_str = {
|
||||
{ ModelCacheStatus::NOT_READ, "not_read_models" },
|
||||
};
|
||||
|
||||
std::vector<std::string> find_models(const std::vector<std::string> &dirs, const std::string& regexp = ".*");
|
||||
std::pair<std::vector<std::string>, std::pair<ModelCacheStatus, std::vector<std::string>>>
|
||||
find_models(const std::vector<std::string> &dirs, const std::string& regexp = ".*");
|
||||
|
||||
// model_cache_status: model_list
|
||||
std::map<ModelCacheStatus, std::vector<std::string>> cache_models(
|
||||
@ -67,10 +70,136 @@ std::map<ModelCacheStatus, std::vector<std::string>> cache_models(
|
||||
void save_model_status_to_file(const std::map<ModelCacheStatus, std::vector<std::string>>& caching_status,
|
||||
const std::string& output_dir);
|
||||
|
||||
std::pair<std::shared_ptr<ov::Model>, std::map<std::string, InputInfo>>
|
||||
inline ExtractedPattern
|
||||
generate_model(const std::set<std::shared_ptr<ov::Node>>& nodes,
|
||||
const std::shared_ptr<ov::Node>& start_node,
|
||||
std::unordered_set<std::string>& checked_ops);
|
||||
std::unordered_set<std::string>& checked_ops,
|
||||
const std::string& extractor_name) {
|
||||
std::unordered_map<std::string, std::shared_ptr<ov::Node>> model_map;
|
||||
// to create reults: { out_op_name, out_ports_without_target_inputs }
|
||||
std::unordered_map<std::string, std::unordered_set<size_t>> model_output_nodes;
|
||||
std::map<std::string, InputInfo> input_info;
|
||||
ov::ParameterVector params;
|
||||
{
|
||||
// prepare map { original_op_name, cloned_op }
|
||||
size_t functional_op_cnt = 0;
|
||||
for (const auto& op : nodes) {
|
||||
auto op_name = op->get_friendly_name();
|
||||
checked_ops.insert(op_name);
|
||||
auto cloned_op = clone_node(op, true, false, op->get_friendly_name());
|
||||
model_map.insert({ op_name, cloned_op });
|
||||
|
||||
size_t output_cnt = op->outputs().size();
|
||||
std::vector<size_t> out_ports(output_cnt);
|
||||
std::iota(out_ports.begin(), out_ports.end(), 0);
|
||||
std::unordered_set<size_t> out_ports_set(out_ports.begin(), out_ports.end());
|
||||
model_output_nodes.insert({ op_name, out_ports_set });
|
||||
if (!ov::op::util::is_output(op) && !ov::op::util::is_constant(op) && !ov::op::util::is_parameter(op)) {
|
||||
++functional_op_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
if (functional_op_cnt < 2) {
|
||||
throw std::runtime_error("Incorrect node number to create model");
|
||||
}
|
||||
// replace new inputs by taken from graph if possible
|
||||
for (const auto& op : nodes) {
|
||||
int filled_input_idx = -1;
|
||||
std::vector<size_t> not_filled_ports;
|
||||
auto in_cnt = op->inputs().size();
|
||||
auto cloned_op = model_map[op->get_friendly_name()];
|
||||
std::map<std::string, InputInfo> this_input_info = get_input_info_by_node(cloned_op);
|
||||
for (size_t in_idx = 0; in_idx < in_cnt; ++in_idx) {
|
||||
auto in_node = op->get_input_node_ptr(in_idx)->shared_from_this();
|
||||
for (size_t in_out_idx = 0; in_out_idx < in_node->outputs().size(); ++in_out_idx) {
|
||||
for (const auto& target_input : in_node->output(in_out_idx).get_target_inputs()) {
|
||||
auto out_in_node = target_input.get_node()->shared_from_this();
|
||||
if (out_in_node == op) {
|
||||
auto in_node_name = in_node->get_friendly_name();
|
||||
auto in_cloned_node = cloned_op->get_input_node_shared_ptr(in_idx);
|
||||
// if op input node is in subgraph
|
||||
if (model_map.count(in_node_name)) {
|
||||
auto in_node = model_map[in_node_name];
|
||||
auto in_cloned_friendly_name = in_cloned_node->get_friendly_name();
|
||||
ov::replace_output_update_name(in_cloned_node->get_default_output(), in_node->output(in_out_idx));
|
||||
in_cloned_node->clear_control_dependencies();
|
||||
if (ov::op::util::is_parameter(in_node)) {
|
||||
auto param = std::dynamic_pointer_cast<ov::op::v0::Parameter>(in_node);
|
||||
params.push_back(param);
|
||||
this_input_info.insert({ in_node->get_friendly_name(), this_input_info[in_cloned_friendly_name]});
|
||||
} else if (ov::op::util::is_constant(in_node)) {
|
||||
auto op_to_replace = std::dynamic_pointer_cast<ov::op::v0::Constant>(in_node);
|
||||
auto param = convert_const_to_param(op_to_replace);
|
||||
if (param != nullptr) {
|
||||
params.push_back(param);
|
||||
}
|
||||
// insert in_info with updated in_name
|
||||
this_input_info.insert({ in_node->get_friendly_name(), this_input_info[in_cloned_friendly_name]});
|
||||
}
|
||||
// remove in_info with old name from input info
|
||||
this_input_info.erase(in_cloned_friendly_name);
|
||||
filled_input_idx++;
|
||||
model_output_nodes[in_node_name].erase(in_out_idx);
|
||||
if (model_output_nodes[in_node_name].empty()) {
|
||||
model_output_nodes.erase(in_node_name);
|
||||
}
|
||||
} else if (ov::op::util::is_parameter(in_cloned_node)) {
|
||||
auto param = std::dynamic_pointer_cast<ov::op::v0::Parameter>(in_cloned_node);
|
||||
params.push_back(param);
|
||||
} else if (ov::op::util::is_constant(in_cloned_node)) {
|
||||
auto op_to_replace = std::dynamic_pointer_cast<ov::op::v0::Constant>(in_cloned_node);
|
||||
auto param = convert_const_to_param(op_to_replace);
|
||||
if (param != nullptr) {
|
||||
params.push_back(param);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (filled_input_idx == in_idx) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this_input_info.empty()) {
|
||||
input_info.insert(this_input_info.begin(), this_input_info.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
ov::ResultVector results;
|
||||
for (const auto& out_node_name : model_output_nodes) {
|
||||
auto out_node = model_map[out_node_name.first];
|
||||
if (ov::op::util::is_output(out_node)) {
|
||||
results.push_back(std::dynamic_pointer_cast<ov::op::v0::Result>(out_node));
|
||||
} else {
|
||||
for (const auto& out_port_id : out_node_name.second) {
|
||||
results.push_back(std::make_shared<ov::op::v0::Result>(out_node->output(out_port_id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
auto model = std::make_shared<ov::Model>(results, params);
|
||||
std::string string_to_hash;
|
||||
for (const auto& op : model->get_ordered_ops()) {
|
||||
std::ostringstream result;
|
||||
result << op->get_type_info();
|
||||
for (const auto& in : op->inputs()) {
|
||||
result << in.get_element_type();
|
||||
result << in.get_partial_shape().rank();
|
||||
result << in.get_partial_shape().is_static();
|
||||
}
|
||||
for (const auto& out : op->outputs()) {
|
||||
result << out.get_element_type();
|
||||
result << out.get_partial_shape().rank();
|
||||
result << out.get_partial_shape().is_static();
|
||||
}
|
||||
string_to_hash += result.str();
|
||||
}
|
||||
for (const auto& in : input_info) {
|
||||
string_to_hash += (in.second.is_const ? "1" : "0");
|
||||
}
|
||||
auto h1 = std::hash<std::string>{}(string_to_hash);
|
||||
model->set_friendly_name(std::to_string(h1));
|
||||
return { model, input_info, extractor_name };
|
||||
}
|
||||
|
||||
} // namespace subgraph_dumper
|
||||
} // namespace tools
|
||||
|
@ -36,6 +36,9 @@ std::shared_ptr<ov::Node> clone_node(std::shared_ptr<ov::Node> node,
|
||||
bool is_copy_const_node = false,
|
||||
std::string node_name = "");
|
||||
|
||||
|
||||
std::shared_ptr<ov::op::v0::Parameter> convert_const_to_param(const std::shared_ptr<ov::op::v0::Constant>& constant_node);
|
||||
|
||||
// all inputs are defined as parameters and contains detailed info in meta
|
||||
std::shared_ptr<ov::Model> generate_model_by_node(const std::shared_ptr<ov::Node>& node);
|
||||
|
||||
|
@ -20,31 +20,6 @@ bool ICache::serialize_model(const std::pair<std::shared_ptr<ov::Model>, MetaInf
|
||||
const std::string& rel_serialization_dir) {
|
||||
std::shared_ptr<ov::Model> model = graph_info.first;
|
||||
MetaInfo meta = graph_info.second;
|
||||
std::map<std::shared_ptr<ov::Node>, std::shared_ptr<ov::Node>> nodes;
|
||||
ov::ParameterVector param_vector;
|
||||
for (const auto& op : model->get_ordered_ops()) {
|
||||
std::shared_ptr<ov::op::v0::Parameter> param = nullptr;
|
||||
if (ov::op::util::is_parameter(op)) {
|
||||
param = std::dynamic_pointer_cast<ov::op::v0::Parameter>(op);
|
||||
} else if (ov::op::util::is_constant(op)) {
|
||||
auto op_to_replace = std::dynamic_pointer_cast<ov::op::v0::Constant>(op);
|
||||
if (op_to_replace->get_byte_size() > 1024) {
|
||||
param = std::make_shared<ov::op::v0::Parameter>(
|
||||
op_to_replace->get_output_element_type(0), op_to_replace->get_output_partial_shape(0));
|
||||
param->set_friendly_name(op_to_replace->get_friendly_name());
|
||||
nodes.insert({ op_to_replace, param });
|
||||
}
|
||||
}
|
||||
if (param != nullptr) {
|
||||
param_vector.push_back(param);
|
||||
}
|
||||
}
|
||||
if (!nodes.empty()) {
|
||||
for (const auto& node : nodes) {
|
||||
model->replace_node(node.first, node.second);
|
||||
}
|
||||
model = std::make_shared<ov::Model>(model->get_results(), param_vector);
|
||||
}
|
||||
|
||||
std::string model_name = model->get_friendly_name();
|
||||
std::string abs_searilization_dir = ov::util::path_join({ m_serialization_dir, rel_serialization_dir });
|
||||
@ -67,7 +42,8 @@ bool ICache::serialize_model(const std::pair<std::shared_ptr<ov::Model>, MetaInf
|
||||
} catch (std::exception &e) {
|
||||
std::cout << "[ ERROR ] Failed to serialize model: " << model_name
|
||||
<< ". Exception: " << e.what() << std::endl;
|
||||
ov::test::utils::removeIRFiles(xml_path, bin_path);
|
||||
ov::test::utils::removeFile(xml_path);
|
||||
ov::test::utils::removeFile(bin_path);
|
||||
ov::test::utils::removeFile(meta_path);
|
||||
if (std::string(e.what()).find("Can't open") == std::string::npos) {
|
||||
return false;
|
||||
|
@ -2,10 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "openvino/op/util/op_types.hpp"
|
||||
#include "openvino/util/file_util.hpp"
|
||||
|
||||
#include "functional_test_utils/ov_plugin_cache.hpp"
|
||||
#include "common_test_utils/graph_comparator.hpp"
|
||||
#include "common_test_utils/file_utils.hpp"
|
||||
|
||||
#include "cache/graph_cache.hpp"
|
||||
#include "utils/node.hpp"
|
||||
@ -26,31 +30,73 @@ void GraphCache::update_cache(const std::shared_ptr<ov::Model>& model,
|
||||
return;
|
||||
}
|
||||
while (!extracted_patterns.empty()) {
|
||||
auto it = extracted_patterns.begin();
|
||||
update_cache(it->first, model_meta_data, it->second, model_total_op);
|
||||
auto it = *extracted_patterns.begin();
|
||||
update_cache(std::get<0>(it), model_meta_data, std::get<1>(it), std::get<2>(it), model_total_op);
|
||||
extracted_patterns.pop_front();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void GraphCache::update_cache(const std::shared_ptr<ov::Model>& extracted_model, const std::string& model_path,
|
||||
const std::map<std::string, InputInfo>& input_info, size_t model_op_cnt) {
|
||||
std::shared_ptr<ov::Model> model_to_update = nullptr;
|
||||
for (const auto& cached_model : m_graph_cache) {
|
||||
if (m_manager.match(cached_model.first, extracted_model)) {
|
||||
model_to_update = cached_model.first;
|
||||
std::map<std::string, InputInfo>& input_info, const std::string& extractor_name, size_t model_op_cnt) {
|
||||
// todo: check the number 8GB
|
||||
if (m_graph_cache_bytesize >> 33 > 0) {
|
||||
std::cout << "[ GRAPH CACHE ][ WARNING ] Cache size > 8 GB. Serialize graph cache" << std::endl;
|
||||
serialize_cache();
|
||||
// m_graph_cache.clear();
|
||||
m_graph_cache_bytesize = 0;
|
||||
}
|
||||
|
||||
auto graph_name = extracted_model->get_friendly_name();
|
||||
std::string serialized_model_path = "";
|
||||
for (const auto& extractor : m_manager.get_extractors()) {
|
||||
auto tmp_serialized_model_path = ov::util::path_join({ m_serialization_dir, "subgraph", extractor.first, graph_name + ".xml" });
|
||||
if (ov::util::file_exists(serialized_model_path)) {
|
||||
serialized_model_path = tmp_serialized_model_path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ov::Model> model_to_update = nullptr;
|
||||
// if cached model was serialized
|
||||
if (!serialized_model_path.empty()) {
|
||||
std::cout << "[ GRAPH CACHE ][ INFO ] Reading cached model: " << serialized_model_path << std::endl;
|
||||
auto bin_path = ov::test::utils::replaceExt(serialized_model_path, ".bin");
|
||||
auto meta_path = ov::test::utils::replaceExt(serialized_model_path, ".meta");
|
||||
auto cached_model = ov::test::utils::PluginCache::get().core()->read_model(serialized_model_path);
|
||||
auto cached_meta = MetaInfo::read_meta_from_file(meta_path);
|
||||
|
||||
ov::test::utils::removeFile(serialized_model_path);
|
||||
ov::test::utils::removeFile(bin_path);
|
||||
ov::test::utils::removeFile(meta_path);
|
||||
m_graph_cache.insert({ cached_model, cached_meta });
|
||||
m_graph_cache_bytesize += cached_model->get_graph_size();
|
||||
model_to_update = cached_model;
|
||||
input_info = m_manager.align_input_info(extracted_model, model_to_update,
|
||||
input_info, cached_meta.get_input_info());
|
||||
} else {
|
||||
for (const auto& cached_model : m_graph_cache) {
|
||||
if (m_manager.match(extracted_model, cached_model.first,
|
||||
input_info, cached_model.second.get_input_info())) {
|
||||
model_to_update = cached_model.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto this_op_cnt = extracted_model->get_ops().size() -
|
||||
extracted_model->get_parameters().size() - extracted_model->get_results().size();
|
||||
if (model_to_update == nullptr) {
|
||||
auto meta = MetaInfo(model_path, input_info, model_op_cnt);
|
||||
auto meta = MetaInfo(model_path, input_info, model_op_cnt, this_op_cnt, extractor_name);
|
||||
m_graph_cache.insert({ extracted_model, meta });
|
||||
m_graph_cache_bytesize += extracted_model->get_graph_size();
|
||||
return;
|
||||
}
|
||||
m_graph_cache[model_to_update].update(model_path, input_info, model_op_cnt);
|
||||
m_graph_cache[model_to_update].update(model_path, input_info, model_op_cnt, this_op_cnt, extractor_name);
|
||||
auto cached_model_size = model_to_update->get_graph_size();
|
||||
auto pattern_model_size = extracted_model->get_graph_size();
|
||||
if (pattern_model_size < cached_model_size) {
|
||||
m_graph_cache_bytesize -= (cached_model_size - pattern_model_size);
|
||||
auto meta = m_graph_cache[model_to_update];
|
||||
m_graph_cache.erase(model_to_update);
|
||||
m_graph_cache.insert({extracted_model, meta});
|
||||
@ -58,11 +104,18 @@ void GraphCache::update_cache(const std::shared_ptr<ov::Model>& extracted_model,
|
||||
}
|
||||
|
||||
void GraphCache::serialize_cache() {
|
||||
for (const auto& cache_item : m_graph_cache) {
|
||||
serialize_model(cache_item, "subgraph");
|
||||
}
|
||||
// for (const auto& cache_item : m_graph_cache) {
|
||||
auto it = m_graph_cache.begin();
|
||||
while (it != m_graph_cache.end()) {
|
||||
auto rel_dir = ov::util::path_join({ "subgraph", it->second.get_any_extractor() });
|
||||
serialize_model(*it, rel_dir);
|
||||
m_graph_cache.erase(it->first);
|
||||
it = m_graph_cache.begin();
|
||||
}
|
||||
auto a = 0;
|
||||
// }
|
||||
}
|
||||
|
||||
} // namespace subgraph_dumper
|
||||
} // namespace tools
|
||||
} // namespace ov
|
||||
} // namespace ov
|
||||
|
@ -15,16 +15,20 @@ namespace subgraph_dumper {
|
||||
unsigned long MetaInfo::MIN_MODEL_PRIORITY = std::numeric_limits<unsigned long>::max();
|
||||
unsigned long MetaInfo::MAX_MODEL_PRIORITY = std::numeric_limits<unsigned long>::min();
|
||||
|
||||
MetaInfo::MetaInfo(const std::string& _model_path, const std::map<std::string, InputInfo>& _input_info, size_t _total_op_cnt, size_t model_priority) {
|
||||
MetaInfo::MetaInfo(const std::string& _model_path, const std::map<std::string, InputInfo>& _input_info,
|
||||
size_t _total_op_cnt, size_t _this_op_cnt, const std::string& extractor, size_t model_priority) {
|
||||
unsigned long tmp_graph_priority = _total_op_cnt * model_priority;
|
||||
if (tmp_graph_priority < MIN_MODEL_PRIORITY) MIN_MODEL_PRIORITY = tmp_graph_priority;
|
||||
if (tmp_graph_priority > MAX_MODEL_PRIORITY) MAX_MODEL_PRIORITY = tmp_graph_priority;
|
||||
if (_model_path != "") {
|
||||
model_info.insert({ get_model_name_by_path(_model_path), ModelInfo(_model_path, _total_op_cnt, model_priority) });
|
||||
model_info.insert({ get_model_name_by_path(_model_path), ModelInfo(_model_path, _total_op_cnt, _this_op_cnt, model_priority) });
|
||||
}
|
||||
if (!_input_info.empty()) {
|
||||
input_info = _input_info;
|
||||
}
|
||||
if (!extractor.empty()) {
|
||||
extractors = { extractor };
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long MetaInfo::get_abs_graph_priority() {
|
||||
@ -42,6 +46,53 @@ double MetaInfo::get_graph_priority() {
|
||||
return diff / delta;
|
||||
}
|
||||
|
||||
MetaInfo MetaInfo::read_meta_from_file(const std::string& meta_path) {
|
||||
pugi::xml_document doc;
|
||||
doc.load_file(meta_path.c_str());
|
||||
std::map<std::string, ModelInfo> model_info;
|
||||
{
|
||||
auto model_xml_root = doc.child("meta_info").child("models");
|
||||
for (const auto& model_child : model_xml_root.children()) {
|
||||
ModelInfo tmp_model_info;
|
||||
tmp_model_info.this_op_cnt = model_child.attribute("this_op_count").as_uint();
|
||||
tmp_model_info.total_op_cnt = model_child.attribute("total_op_count").as_uint();
|
||||
for (const auto& path : model_child.child("path")) {
|
||||
tmp_model_info.model_paths.insert(std::string(path.attribute("path").value()));
|
||||
}
|
||||
model_info.insert({ std::string(model_child.attribute("name").value()), tmp_model_info });
|
||||
}
|
||||
}
|
||||
std::map<std::string, InputInfo> input_info;
|
||||
{
|
||||
auto input_info_xml = doc.child("meta_info").child("input_info");
|
||||
for (const auto &input : input_info_xml.children()) {
|
||||
auto in_name = std::string(input.attribute("id").value());
|
||||
ov::tools::subgraph_dumper::InputInfo in_info;
|
||||
in_info.is_const = input.attribute("convert_to_const").as_bool();
|
||||
if (std::string(input.attribute("min").value()) != "undefined") {
|
||||
in_info.ranges.min = input.attribute("min").as_double();
|
||||
} else {
|
||||
in_info.ranges.min = DEFAULT_MIN_VALUE;
|
||||
}
|
||||
if (std::string(input.attribute("max").value()) != "undefined") {
|
||||
in_info.ranges.max = input.attribute("max").as_double();
|
||||
} else {
|
||||
in_info.ranges.min = DEFAULT_MAX_VALUE;
|
||||
}
|
||||
input_info.insert({in_name, in_info});
|
||||
}
|
||||
}
|
||||
std::unordered_set<std::string> extractors;
|
||||
{
|
||||
auto extractors_xml = doc.child("meta_info").child("extractors");
|
||||
for (const auto& extractor : extractors_xml.children()) {
|
||||
extractors.insert(std::string(extractor.attribute("name").value()));
|
||||
}
|
||||
}
|
||||
auto new_meta = MetaInfo(input_info, model_info, extractors);
|
||||
return new_meta;
|
||||
}
|
||||
|
||||
void MetaInfo::serialize(const std::string& serialization_path) {
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_node root = doc.append_child("meta_info");
|
||||
@ -56,6 +107,12 @@ void MetaInfo::serialize(const std::string& serialization_path) {
|
||||
model_node.append_child("path").append_child("model").append_attribute("path").set_value(model_path.c_str());
|
||||
}
|
||||
}
|
||||
if (!extractors.empty()) {
|
||||
auto extractors_node = root.append_child("extractors");
|
||||
for (const auto& extractor : extractors) {
|
||||
extractors_node.append_child("extractor").append_attribute("name").set_value(extractor.c_str());
|
||||
}
|
||||
}
|
||||
double graph_priority = get_graph_priority();
|
||||
root.append_child("graph_priority").append_attribute("value").set_value(graph_priority);
|
||||
auto ports_info = root.append_child("input_info");
|
||||
@ -80,6 +137,8 @@ void MetaInfo::serialize(const std::string& serialization_path) {
|
||||
void MetaInfo::update(const std::string& _model_path,
|
||||
const std::map<std::string, InputInfo>& _input_info,
|
||||
size_t _total_op_cnt,
|
||||
size_t _this_op_cnt,
|
||||
const std::string& extractor,
|
||||
const std::vector<std::string>& ignored_inputs) {
|
||||
if (input_info.size() != _input_info.size()) {
|
||||
throw std::runtime_error("Incompatible input info!");
|
||||
@ -90,7 +149,7 @@ void MetaInfo::update(const std::string& _model_path,
|
||||
model_info.at(model_name).model_paths.insert(_model_path);
|
||||
model_info.at(model_name).total_op_cnt += _total_op_cnt;
|
||||
}
|
||||
model_info.at(model_name).this_op_cnt++;
|
||||
model_info.at(model_name).this_op_cnt += _this_op_cnt;
|
||||
} else {
|
||||
model_info.insert({ model_name, ModelInfo(_model_path, _total_op_cnt) });\
|
||||
}
|
||||
@ -112,13 +171,16 @@ void MetaInfo::update(const std::string& _model_path,
|
||||
if (abs_graph_priority > MAX_MODEL_PRIORITY) MAX_MODEL_PRIORITY = abs_graph_priority;
|
||||
if (abs_graph_priority < MIN_MODEL_PRIORITY) MIN_MODEL_PRIORITY = abs_graph_priority;
|
||||
}
|
||||
if (!extractor.empty()) {
|
||||
extractors.insert(extractor);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, InputInfo> MetaInfo::get_input_info() {
|
||||
std::map<std::string, InputInfo> MetaInfo::get_input_info() const {
|
||||
return input_info;
|
||||
}
|
||||
|
||||
std::map<std::string, ModelInfo> MetaInfo::get_model_info() {
|
||||
std::map<std::string, ModelInfo> MetaInfo::get_model_info() const {
|
||||
return model_info;
|
||||
}
|
||||
|
||||
|
@ -83,11 +83,12 @@ void OpCache::update_cache(const std::shared_ptr<ov::Node>& node,
|
||||
}
|
||||
|
||||
size_t priority = get_node_priority_by_version(cloned_node);
|
||||
auto meta = MetaInfo(model_path, get_input_info_by_node(cloned_node), model_op_cnt, priority);
|
||||
auto meta = MetaInfo(model_path, get_input_info_by_node(cloned_node), model_op_cnt, 1, "", priority);
|
||||
if (find_op_in_cache != nullptr) {
|
||||
std::cout << "[ INFO ][ OP CACHE ] Update cache node: " << cloned_node->get_type_info().name <<
|
||||
" " << find_op_in_cache->get_friendly_name() << std::endl;
|
||||
m_ops_cache[find_op_in_cache].update(model_path, get_input_info_by_node(cloned_node), model_op_cnt, ignored_input_names);
|
||||
// std::cout << "[ INFO ][ OP CACHE ] Update cache node: " << cloned_node->get_type_info().name << cloned_node->get_friendly_name() <<
|
||||
// " " << find_op_in_cache->get_friendly_name() << std::endl;
|
||||
m_ops_cache[find_op_in_cache].update(
|
||||
model_path, get_input_info_by_node(cloned_node), model_op_cnt, 1, "", ignored_input_names);
|
||||
}
|
||||
if (find_op_in_cache > cloned_node) {
|
||||
meta = m_ops_cache[find_op_in_cache];
|
||||
@ -95,8 +96,8 @@ void OpCache::update_cache(const std::shared_ptr<ov::Node>& node,
|
||||
find_op_in_cache = nullptr;
|
||||
}
|
||||
if (find_op_in_cache == nullptr) {
|
||||
std::cout << "[ INFO ][ OP CACHE ] Insert node: " << cloned_node->get_type_info().name <<
|
||||
" " << cloned_node->get_friendly_name() << " to Cache" << std::endl;
|
||||
// std::cout << "[ INFO ][ OP CACHE ] Insert node: " << cloned_node->get_type_info().name <<
|
||||
// " " << cloned_node->get_friendly_name() << " to Cache" << std::endl;
|
||||
m_ops_cache.insert({ cloned_node, meta });
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ int main(int argc, char *argv[]) {
|
||||
std::vector<std::string> dirs = ov::test::utils::splitStringByDelimiter(FLAGS_input_folders);
|
||||
|
||||
std::vector<std::string> models;
|
||||
std::map<ModelCacheStatus, std::vector<std::string>> cache_model_status;
|
||||
|
||||
if (!ov::test::utils::directoryExists(FLAGS_output_folder)) {
|
||||
std::string msg = "Output directory (" + FLAGS_output_folder + ") doesn't not exist! The directory will be created.";
|
||||
@ -27,7 +28,9 @@ int main(int argc, char *argv[]) {
|
||||
ov::test::utils::createDirectoryRecursive(FLAGS_output_folder);
|
||||
}
|
||||
try {
|
||||
models = find_models(dirs, FLAGS_path_regex);
|
||||
auto all_models = find_models(dirs, FLAGS_path_regex);
|
||||
models = all_models.first;
|
||||
cache_model_status.insert(all_models.second);
|
||||
} catch (std::runtime_error& e) {
|
||||
std::cout << "[ INFO ] Try 'subgraphsDumper -h' for more information. \nException: " << e.what() << std::endl;
|
||||
return 1;
|
||||
@ -39,27 +42,39 @@ int main(int argc, char *argv[]) {
|
||||
caches.push_back(OpCache::get());
|
||||
}
|
||||
if (FLAGS_cache_type == "GRAPH" || FLAGS_cache_type.empty()) {
|
||||
// todo: iefode: to check and enable it in CI
|
||||
// std::cout << "[ INFO ] GraphCache is enabled!" << std::endl;
|
||||
// caches.push_back(GraphCache::get());
|
||||
std::cout << "[ INFO ] GraphCache is enabled!" << std::endl;
|
||||
caches.push_back(GraphCache::get());
|
||||
}
|
||||
|
||||
for (auto& cache : caches) {
|
||||
cache->set_serialization_dir(FLAGS_output_folder);
|
||||
}
|
||||
std::map<ModelCacheStatus, std::vector<std::string>> cache_model_status;
|
||||
// Upload previously cached graphs to cache
|
||||
if (!FLAGS_local_cache.empty()) {
|
||||
auto cachedOps = find_models(local_cache_dirs);
|
||||
cache_model_status = cache_models(caches, cachedOps, FLAGS_extract_body);
|
||||
auto cached_ops = find_models(local_cache_dirs);
|
||||
// todo: add normal caching with meta info reading
|
||||
auto this_cache_model_status = cache_models(caches, cached_ops.first, FLAGS_extract_body);
|
||||
auto not_read_model = cached_ops.second;
|
||||
for (auto& model_status : cache_model_status) {
|
||||
auto& key = model_status.first;
|
||||
auto& value = model_status.second;
|
||||
if (not_read_model.first == key) {
|
||||
value.insert(value.end(), not_read_model.second.begin(), not_read_model.second.end());
|
||||
}
|
||||
if (this_cache_model_status.count(key)) {
|
||||
value.insert(value.end(), this_cache_model_status[key].begin(), this_cache_model_status[key].end());
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto tmp_cache_model_status = cache_models(caches, models, FLAGS_extract_body);
|
||||
cache_model_status.insert(tmp_cache_model_status.begin(), tmp_cache_model_status.end());
|
||||
}
|
||||
for (auto& cache : caches) {
|
||||
cache->set_serialization_dir(FLAGS_output_folder);
|
||||
cache->serialize_cache();
|
||||
auto this_cache_model_status = cache_models(caches, models, FLAGS_extract_body);
|
||||
for (auto& model_status : cache_model_status) {
|
||||
auto& key = model_status.first;
|
||||
auto& value = model_status.second;
|
||||
if (this_cache_model_status.count(key)) {
|
||||
value.insert(value.end(), this_cache_model_status[key].begin(), this_cache_model_status[key].end());
|
||||
}
|
||||
}
|
||||
}
|
||||
save_model_status_to_file(cache_model_status, FLAGS_output_folder);
|
||||
return cache_model_status[ModelCacheStatus::NOT_FULLY_CACHED].empty() && cache_model_status[ModelCacheStatus::NOT_READ].empty();
|
||||
|
@ -15,8 +15,7 @@ using namespace ov::tools::subgraph_dumper;
|
||||
|
||||
std::unordered_set<std::string>
|
||||
FusedNamesExtractor::extract_compiled_model_names(const std::shared_ptr<ov::Model>& model) {
|
||||
auto core = ov::test::utils::PluginCache::get().core();
|
||||
auto compiled_model = core->compile_model(model);
|
||||
auto compiled_model = core->compile_model(model, device);
|
||||
std::unordered_set<std::string> compiled_op_name;
|
||||
for (const auto& compiled_op : compiled_model.get_runtime_model()->get_ordered_ops()) {
|
||||
const auto& rt_info = compiled_op->get_rt_info();
|
||||
@ -27,6 +26,11 @@ FusedNamesExtractor::extract_compiled_model_names(const std::shared_ptr<ov::Mode
|
||||
return compiled_op_name;
|
||||
}
|
||||
|
||||
FusedNamesExtractor::FusedNamesExtractor() {
|
||||
core = ov::test::utils::PluginCache::get().core();
|
||||
device = *(core->get_available_devices().begin());
|
||||
}
|
||||
|
||||
std::list<ExtractedPattern>
|
||||
FusedNamesExtractor::extract(const std::shared_ptr<ov::Model> &model,
|
||||
bool is_extract_body) {
|
||||
@ -34,16 +38,23 @@ FusedNamesExtractor::extract(const std::shared_ptr<ov::Model> &model,
|
||||
std::list<ExtractedPattern> matched_patterns;
|
||||
std::unordered_set<std::string> checked_ops;
|
||||
std::set<std::shared_ptr<ov::Node>> nodes;
|
||||
std::shared_ptr<ov::Node> start_node = nullptr;
|
||||
for (const auto& op : model->get_ordered_ops()) {
|
||||
auto op_name = op->get_friendly_name();
|
||||
if (is_node_to_skip(op) || checked_ops.count(op_name)) {
|
||||
continue;
|
||||
}
|
||||
if (start_node == nullptr) {
|
||||
start_node = op;
|
||||
if (compiled_op_name.count(op_name)) {
|
||||
try {
|
||||
matched_patterns.push_back(generate_model(nodes, checked_ops, extractor_name));
|
||||
} catch(std::exception& e) {
|
||||
if (std::string(e.what()) != "Incorrect node number to create model") {
|
||||
std::cout << "[ WARNING ] Impossible to generate network and add to GraphCache: " <<e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
nodes.clear();
|
||||
} else {
|
||||
nodes.insert(op);
|
||||
}
|
||||
nodes.insert(op);
|
||||
if (is_extract_body) {
|
||||
if (std::dynamic_pointer_cast<ov::op::v0::TensorIterator>(op)) {
|
||||
auto ti = ov::as_type_ptr<ov::op::v0::TensorIterator>(op);
|
||||
@ -65,20 +76,13 @@ FusedNamesExtractor::extract(const std::shared_ptr<ov::Model> &model,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!compiled_op_name.count(op_name)) {
|
||||
try {
|
||||
matched_patterns.push_back(generate_model(nodes, start_node, checked_ops));
|
||||
} catch(std::exception& e) {
|
||||
std::cout << "[ ERROR ] Impossible to generate network and add to GraphCache: " <<e.what() << std::endl;
|
||||
}
|
||||
start_node = nullptr;
|
||||
nodes.clear();
|
||||
}
|
||||
}
|
||||
try {
|
||||
matched_patterns.push_back(generate_model(nodes, start_node, checked_ops));
|
||||
matched_patterns.push_back(generate_model(nodes, checked_ops, extractor_name));
|
||||
} catch(std::exception& e) {
|
||||
std::cout << "[ ERROR ] Impossible to generate network and add to GraphCache: " << e.what() << std::endl;
|
||||
if (std::string(e.what()) != "Incorrect node number to create model") {
|
||||
std::cout << "[ WARNING ] Impossible to generate network and add to GraphCache: " <<e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
return matched_patterns;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <chrono>
|
||||
#include "matchers/subgraph/manager.hpp"
|
||||
|
||||
using namespace ov::tools::subgraph_dumper;
|
||||
@ -16,12 +16,71 @@ bool ExtractorsManager::match(const std::shared_ptr<ov::Model> &model,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ExtractorsManager::match(const std::shared_ptr<ov::Model> &model,
|
||||
const std::shared_ptr<ov::Model> &ref,
|
||||
std::map<std::string, InputInfo> &in_info,
|
||||
const std::map<std::string, InputInfo> &in_info_ref) {
|
||||
if (match(model, ref)) {
|
||||
try {
|
||||
auto new_input_info = align_input_info(model, ref, in_info, in_info_ref);
|
||||
in_info = new_input_info;
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<std::string, InputInfo>
|
||||
ExtractorsManager::align_input_info(const std::shared_ptr<ov::Model>& model,
|
||||
const std::shared_ptr<ov::Model>& model_ref,
|
||||
const std::map<std::string, InputInfo>& in_info,
|
||||
const std::map<std::string, InputInfo>& in_info_ref) {
|
||||
std::map<std::string, InputInfo> new_input_info = in_info;
|
||||
bool is_update_required = false;
|
||||
for (const auto& in_info_item : in_info_ref) {
|
||||
if (!in_info.count(in_info_item.first)) {
|
||||
is_update_required = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_update_required) {
|
||||
std::map<std::string, InputInfo> new_ref_input_info = in_info_ref;
|
||||
// align matched model names
|
||||
auto ref_model_ops = model_ref->get_ordered_ops();
|
||||
auto model_ops = model->get_ordered_ops();
|
||||
size_t ordered_ops_size = model_ops.size();
|
||||
if (ordered_ops_size != ref_model_ops.size()) {
|
||||
throw std::runtime_error("Matched models are different!");
|
||||
}
|
||||
for (size_t i = 0; i < ordered_ops_size; ++i) {
|
||||
auto model_op_name = model_ops[i]->get_friendly_name();
|
||||
auto model_ref_op_name = ref_model_ops[i]->get_friendly_name();
|
||||
if (in_info.count(model_op_name)) {
|
||||
auto input_info = new_input_info[model_op_name];
|
||||
if (input_info.is_const != new_ref_input_info[model_ref_op_name].is_const) {
|
||||
throw std::runtime_error("Impossible yo update input info!!!");
|
||||
}
|
||||
new_input_info.erase(model_op_name);
|
||||
new_input_info.insert({ model_ref_op_name, input_info });
|
||||
}
|
||||
}
|
||||
}
|
||||
return new_input_info;
|
||||
}
|
||||
|
||||
std::list<ExtractedPattern>
|
||||
ExtractorsManager::extract(const std::shared_ptr<ov::Model> &model, bool is_extract_body) {
|
||||
std::list<ExtractedPattern> result;
|
||||
for (const auto &it : m_extractors) {
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
it.second->set_extractor_name(it.first);
|
||||
auto extracted_patterns = it.second->extract(model, is_extract_body);
|
||||
result.insert(result.end(), extracted_patterns.begin(), extracted_patterns.end());
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
std::cout << "[ INFO ][ EXTRACTOR DURATION ] " << it.first << " " << delta << "ms" << std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -92,11 +92,12 @@ RepeatPatternExtractor::extract(const std::shared_ptr<ov::Model> &model,
|
||||
}
|
||||
for (size_t i = 0; i < start_node_idx.size(); ++i) {
|
||||
try {
|
||||
to_cache.push_back(
|
||||
generate_model(nodes[i], ordered_ops[start_node_idx[i]], checked_ops));
|
||||
to_cache.push_back(generate_model(nodes[i], checked_ops, extractor_name));
|
||||
nodes[i].clear();
|
||||
} catch(std::exception& e) {
|
||||
std::cout << "[ ERROR ] Impossible to generate network and add to GraphCache: " << e.what() << std::endl;
|
||||
if (std::string(e.what()) != "Incorrect node number to create model") {
|
||||
std::cout << "[ WARNING ] Impossible to generate network and add to GraphCache: " <<e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_extract_body) {
|
||||
|
@ -19,7 +19,6 @@ SubgraphExtractor::match(const std::shared_ptr<ov::Model> &model,
|
||||
ref_ordered_ops = ref_model->get_ordered_ops();
|
||||
if (ordered_ops.size() != ref_ordered_ops.size())
|
||||
return false;
|
||||
|
||||
MatchersManager::MatchersMap matchers = {
|
||||
{ "generic_single_op", SingleOpMatcher::Ptr(new SingleOpMatcher) },
|
||||
{ "convolutions", ConvolutionsMatcher::Ptr(new ConvolutionsMatcher) },
|
||||
|
@ -2,96 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "openvino/util/file_util.hpp"
|
||||
#include "functional_test_utils/ov_plugin_cache.hpp"
|
||||
#include "utils/model.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace tools {
|
||||
namespace subgraph_dumper {
|
||||
|
||||
inline std::unordered_map<std::string, std::shared_ptr<ov::Node>>
|
||||
update_nodes(const std::set<std::shared_ptr<ov::Node>>& nodes,
|
||||
const std::shared_ptr<ov::Node>& start_node) {
|
||||
std::unordered_map<std::string, std::shared_ptr<ov::Node>> model_map;
|
||||
std::shared_ptr<ov::Node> cloned_op = nullptr;
|
||||
|
||||
for (const auto& op : nodes) {
|
||||
if (ov::op::util::is_parameter(op) || ov::op::util::is_constant(op) ||
|
||||
ov::op::util::is_output(op)) {
|
||||
continue;
|
||||
}
|
||||
cloned_op = clone_node(op, true, false, "Op_" + std::to_string(model_map.size()));
|
||||
model_map.insert({ op->get_friendly_name(), cloned_op });
|
||||
}
|
||||
|
||||
for (const auto& op : nodes) {
|
||||
if (ov::op::util::is_parameter(op) || ov::op::util::is_constant(op) ||
|
||||
ov::op::util::is_output(op)) {
|
||||
continue;
|
||||
}
|
||||
auto op_name = op->get_friendly_name();
|
||||
cloned_op = model_map[op->get_friendly_name()];
|
||||
size_t inputs_size = op->inputs().size();
|
||||
ov::OutputVector in_out_vector(inputs_size);
|
||||
int filled_input_idx = -1;
|
||||
for (size_t in_idx = 0; in_idx < inputs_size; ++in_idx) {
|
||||
auto in_node = op->get_input_node_ptr(in_idx)->shared_from_this();
|
||||
for (size_t in_out_idx = 0; in_out_idx < in_node->outputs().size(); ++in_out_idx) {
|
||||
for (const auto& target_input : in_node->output(in_out_idx).get_target_inputs()) {
|
||||
auto out_in_node = target_input.get_node()->shared_from_this();
|
||||
if (out_in_node == op) {
|
||||
auto in_node_name = in_node->get_friendly_name();
|
||||
in_out_vector[in_idx] = model_map.count(in_node_name) ?
|
||||
model_map.at(in_node_name)->output(in_out_idx) :
|
||||
cloned_op->get_input_node_ptr(in_idx)->output(0);
|
||||
if (model_map.count(in_node_name)) {
|
||||
filled_input_idx++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (filled_input_idx == in_idx) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// todo: iefode: check this code
|
||||
if (filled_input_idx < 0 && op_name != start_node->get_friendly_name()) {
|
||||
model_map.erase(op_name);
|
||||
} else if (filled_input_idx >= 0) {
|
||||
auto name = cloned_op->get_friendly_name();
|
||||
model_map[op_name] = cloned_op->clone_with_new_inputs(in_out_vector);
|
||||
model_map[op_name]->set_friendly_name(name);
|
||||
}
|
||||
}
|
||||
return model_map;
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<ov::Model>, std::map<std::string, InputInfo>>
|
||||
generate_model(const std::set<std::shared_ptr<ov::Node>>& nodes,
|
||||
const std::shared_ptr<ov::Node>& start_node,
|
||||
std::unordered_set<std::string>& checked_ops) {
|
||||
if (nodes.size() < 2) {
|
||||
throw std::runtime_error("Incorrect node number to create model");
|
||||
}
|
||||
auto model_map = update_nodes(nodes, start_node);
|
||||
if (model_map.size() < 2) {
|
||||
throw std::runtime_error("Incorrect node number to create model");
|
||||
}
|
||||
ov::OutputVector results;
|
||||
std::map<std::string, InputInfo> input_info;
|
||||
for (const auto& op : model_map) {
|
||||
checked_ops.insert(op.first);
|
||||
auto this_input_info = get_input_info_by_node(op.second);
|
||||
input_info.insert(this_input_info.begin(), this_input_info.end());
|
||||
for (size_t j = 0; j < op.second->outputs().size(); ++j) {
|
||||
if (op.second->output(j).get_target_inputs().empty()) {
|
||||
results.push_back(std::make_shared<ov::op::v0::Result>(op.second->output(j)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return { std::make_shared<ov::Model>(results), input_info };
|
||||
}
|
||||
|
||||
void save_model_status_to_file(const std::map<ModelCacheStatus, std::vector<std::string>>& caching_status,
|
||||
const std::string& output_dir) {
|
||||
std::string cache_status_path = ov::util::path_join({output_dir, "model_caching_status"});
|
||||
@ -104,7 +22,9 @@ void save_model_status_to_file(const std::map<ModelCacheStatus, std::vector<std:
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> find_models(const std::vector<std::string> &dirs, const std::string& regexp) {
|
||||
// { models, { not_read_model }}
|
||||
std::pair<std::vector<std::string>, std::pair<ModelCacheStatus, std::vector<std::string>>>
|
||||
find_models(const std::vector<std::string> &dirs, const std::string& regexp) {
|
||||
std::vector<std::string> models, full_content;
|
||||
for (const auto& dir : dirs) {
|
||||
std::vector<std::string> dir_content;
|
||||
@ -120,17 +40,36 @@ std::vector<std::string> find_models(const std::vector<std::string> &dirs, const
|
||||
full_content.insert(full_content.end(), dir_content.begin(), dir_content.end());
|
||||
}
|
||||
}
|
||||
std::multimap<size_t, std::string> models_sorted_by_size;
|
||||
std::vector<std::string> not_read_model;
|
||||
auto in_regex = std::regex(regexp);
|
||||
for (const auto& file : full_content) {
|
||||
if (std::regex_match(file, in_regex)) {
|
||||
for (const auto& model_file : full_content) {
|
||||
if (std::regex_match(model_file, in_regex)) {
|
||||
try {
|
||||
models.emplace_back(file);
|
||||
// models.emplace_back(file);
|
||||
if (ov::util::file_exists(model_file)) {
|
||||
auto core = ov::test::utils::PluginCache::get().core();
|
||||
auto model_size = core->read_model(model_file)->get_graph_size();
|
||||
models_sorted_by_size.insert({ model_size, model_file});
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
std::cout << "[ ERROR ] Impossible to read model: " << file << std::endl << "Exception: " << e.what();
|
||||
not_read_model.emplace_back(model_file);
|
||||
std::cout << "[ ERROR ] Impossible to read model: " << model_file << std::endl << "Exception: " << e.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
return models;
|
||||
// sort model by size with reverse
|
||||
auto model_cnt = models_sorted_by_size.size();
|
||||
models.resize(model_cnt);
|
||||
auto it = models_sorted_by_size.rbegin();
|
||||
for (size_t i = 0; i < model_cnt; ++i) {
|
||||
models[i] = it->second;
|
||||
++it;
|
||||
}
|
||||
std::cout << "[ INFO ] Total model number is " << models.size() << std::endl;
|
||||
return { models, { ModelCacheStatus::NOT_READ, not_read_model } };
|
||||
}
|
||||
|
||||
std::map<ModelCacheStatus, std::vector<std::string>> cache_models(
|
||||
@ -151,9 +90,7 @@ std::map<ModelCacheStatus, std::vector<std::string>> cache_models(
|
||||
try {
|
||||
std::shared_ptr<ov::Model> function = core->read_model(model);
|
||||
try {
|
||||
for (auto& cache : caches) {
|
||||
cache->update_cache(function, model, extract_body);
|
||||
}
|
||||
cache->update_cache(function, model, extract_body);
|
||||
} catch (std::exception &e) {
|
||||
std::cout << "[ ERROR ] Model processing failed with exception:" << std::endl << e.what() << std::endl;
|
||||
model_status = ModelCacheStatus::NOT_FULLY_CACHED;
|
||||
|
@ -10,8 +10,11 @@ namespace subgraph_dumper {
|
||||
std::map<std::string, InputInfo> get_input_info_by_node(const std::shared_ptr<ov::Node>& node) {
|
||||
std::map<std::string, InputInfo> input_info;
|
||||
for (size_t port_id = 0; port_id < node->get_input_size(); ++port_id) {
|
||||
InputInfo in_info;
|
||||
std::shared_ptr<ov::Node> input_node = node->get_input_node_shared_ptr(port_id);
|
||||
if (!ov::op::util::is_parameter(input_node) && !ov::op::util::is_constant(input_node)) {
|
||||
continue;
|
||||
}
|
||||
InputInfo in_info;
|
||||
std::string input_name = input_node->get_friendly_name();
|
||||
if (std::dynamic_pointer_cast<ov::op::v0::Constant>(input_node)) {
|
||||
if (ov::shape_size(input_node->get_output_shape(0)) == 0)
|
||||
@ -80,9 +83,7 @@ std::map<std::string, InputInfo> get_input_info_by_node(const std::shared_ptr<ov
|
||||
break;
|
||||
}}
|
||||
}
|
||||
if (ov::op::util::is_parameter(input_node) || ov::op::util::is_constant(input_node)) {
|
||||
input_info.insert({ input_name, in_info });
|
||||
}
|
||||
input_info.insert({ input_name, in_info });
|
||||
}
|
||||
return input_info;
|
||||
}
|
||||
@ -109,7 +110,7 @@ std::shared_ptr<ov::Node> clone_node(std::shared_ptr<ov::Node> node,
|
||||
const auto constant_input = ov::get_constant_from_source(node->input(i).get_source_output());
|
||||
OPENVINO_SUPPRESS_DEPRECATED_END
|
||||
if (constant_input) {
|
||||
if (is_save_const || constant_input->get_byte_size() <= 1024) {
|
||||
if (is_save_const || constant_input->get_byte_size() < 1024) {
|
||||
auto in_const = std::make_shared<ov::op::v0::Constant>(constant_input->get_element_type(),
|
||||
constant_input->get_shape(),
|
||||
constant_input->get_data_ptr());
|
||||
@ -124,8 +125,9 @@ std::shared_ptr<ov::Node> clone_node(std::shared_ptr<ov::Node> node,
|
||||
param->set_friendly_name(input_name);
|
||||
inputs[i] = param;
|
||||
}
|
||||
if (!has_parameters && !is_copy_const_node) {
|
||||
auto cloned_node = clone_node(node, true, true);
|
||||
std::shared_ptr<ov::Node> cloned_node = nullptr;
|
||||
if (!has_parameters && !is_copy_const_node && !inputs.empty()) {
|
||||
cloned_node = clone_node(node, true, true, node_name);
|
||||
// std::cout << "The operation: " + node->get_friendly_name() + " does not have parameters! Replace first input to parameter!" << std::endl;
|
||||
auto param =
|
||||
std::make_shared<ov::op::v0::Parameter>(cloned_node->get_input_element_type(0), cloned_node->get_input_partial_shape(0));
|
||||
@ -133,13 +135,26 @@ std::shared_ptr<ov::Node> clone_node(std::shared_ptr<ov::Node> node,
|
||||
param->set_friendly_name(param_name);
|
||||
auto node_to_replace = cloned_node->get_input_node_shared_ptr(0);
|
||||
ov::replace_node(node_to_replace, param);
|
||||
return cloned_node;
|
||||
} else {
|
||||
cloned_node = node->clone_with_new_inputs(inputs);
|
||||
cloned_node->set_friendly_name(node_name);
|
||||
}
|
||||
std::shared_ptr<ov::Node> cloned_node = node->clone_with_new_inputs(inputs);
|
||||
cloned_node->set_friendly_name(node_name);
|
||||
return cloned_node;
|
||||
}
|
||||
|
||||
std::shared_ptr<ov::op::v0::Parameter> convert_const_to_param(const std::shared_ptr<ov::op::v0::Constant>& op_to_replace) {
|
||||
if (op_to_replace->get_byte_size() > 1024) {
|
||||
auto param = std::make_shared<ov::op::v0::Parameter>(
|
||||
op_to_replace->get_output_element_type(0), op_to_replace->get_output_partial_shape(0));
|
||||
param->set_friendly_name(op_to_replace->get_friendly_name());
|
||||
if (param != nullptr) {
|
||||
ov::replace_node(op_to_replace, param);
|
||||
}
|
||||
return param;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<ov::Model> generate_model_by_node(const std::shared_ptr<ov::Node>& node) {
|
||||
static size_t model_cnt = 0;
|
||||
auto cloned_node = clone_node(node);
|
||||
|
@ -87,8 +87,6 @@ protected:
|
||||
};
|
||||
|
||||
TEST_F(GraphCacheUnitTest, update_cache_by_graph) {
|
||||
// const std::shared_ptr<ov::Model>& model, const std::string& model_path,
|
||||
// const std::map<std::string, InputInfo>& input_info, size_t model_op_cnt
|
||||
Model_2 test;
|
||||
auto model_to_cache = test.get();
|
||||
std::map<std::string, InputInfo> in_info;
|
||||
@ -97,7 +95,7 @@ TEST_F(GraphCacheUnitTest, update_cache_by_graph) {
|
||||
in_info.insert({ op->get_friendly_name(), InputInfo()});
|
||||
}
|
||||
}
|
||||
this->update_cache(model_to_cache, test_model_path, in_info, model_to_cache->get_ordered_ops().size());
|
||||
this->update_cache(model_to_cache, test_model_path, in_info, "test_extractor", model_to_cache->get_ordered_ops().size());
|
||||
ASSERT_EQ(m_graph_cache.size(), 1);
|
||||
}
|
||||
} // namespace
|
||||
|
@ -64,11 +64,12 @@ protected:
|
||||
std::string test_model_path, test_model_name;
|
||||
std::map<std::string, InputInfo> test_in_info;
|
||||
std::map<std::string, ModelInfo> test_model_info;
|
||||
std::string test_artifacts_dir;
|
||||
std::string test_artifacts_dir, test_extractor_name;
|
||||
|
||||
void SetUp() override {
|
||||
SubgraphsDumperBaseTest::SetUp();
|
||||
test_model_path = "test_model_path.xml";
|
||||
test_extractor_name = "test_extractor";
|
||||
test_model_name = ov::test::utils::replaceExt(test_model_path, "");
|
||||
test_in_info = {{ "test_in_0", InputInfo(DEFAULT_MIN_VALUE, 1, true) }};
|
||||
test_model_info = {{ test_model_name, ModelInfo(test_model_path, 5) }};
|
||||
@ -86,7 +87,8 @@ TEST_F(MetaInfoFuncTest, constructor) {
|
||||
ASSERT_NO_THROW(auto meta = MetaInfo(test_model_name));
|
||||
ASSERT_NO_THROW(auto meta = MetaInfo(test_model_name, test_in_info));
|
||||
ASSERT_NO_THROW(auto meta = MetaInfo(test_model_name, test_in_info, 2));
|
||||
ASSERT_NO_THROW(auto meta = MetaInfo(test_model_name, test_in_info, 3));
|
||||
ASSERT_NO_THROW(auto meta = MetaInfo(test_model_name, test_in_info, 3, 1, test_extractor_name));
|
||||
ASSERT_NO_THROW(auto meta = MetaInfo(test_model_name, test_in_info, 3, 5, test_extractor_name, 5));
|
||||
}
|
||||
|
||||
TEST_F(MetaInfoFuncTest, get_input_info) {
|
||||
@ -101,9 +103,15 @@ TEST_F(MetaInfoFuncTest, get_model_info) {
|
||||
ASSERT_EQ(test_meta.get_model_info(), test_model_info);
|
||||
}
|
||||
|
||||
TEST_F(MetaInfoFuncTest, get_any_extractor) {
|
||||
auto test_meta = MetaInfo(test_model_path, test_in_info, 5, 3, test_extractor_name);
|
||||
ASSERT_NO_THROW(test_meta.get_any_extractor());
|
||||
ASSERT_EQ(test_meta.get_any_extractor(), test_extractor_name);
|
||||
}
|
||||
|
||||
TEST_F(MetaInfoFuncTest, update) {
|
||||
std::map<std::string, InputInfo> test_in_info = {{ "test_in_0", InputInfo(DEFAULT_MIN_VALUE, 1, true) }};
|
||||
auto test_meta = MetaInfo(test_model_name, test_in_info);
|
||||
auto test_meta = MetaInfo(test_model_name, test_in_info, 1, 1, test_extractor_name);
|
||||
std::map<std::string, InputInfo> test_input_info_1 = {{ "test_in_0", InputInfo(0, 1, true) }};
|
||||
std::string test_model_1 = "test_model_1";
|
||||
std::string test_model_path_1 = ov::util::path_join({ "path", "to", test_model_1 + ".xml"});
|
||||
@ -111,6 +119,7 @@ TEST_F(MetaInfoFuncTest, update) {
|
||||
ASSERT_ANY_THROW(test_meta.update(test_model_path_1, {{ "test_in_1", InputInfo() }}));
|
||||
ASSERT_ANY_THROW(test_meta.update(test_model_path_1, {{ "test_in_0", InputInfo(0, 1, false) }}));
|
||||
ASSERT_NO_THROW(test_meta.update(test_model_path_1, test_input_info_1));
|
||||
ASSERT_NO_THROW(test_meta.update(test_model_path_1, test_input_info_1, 1, 2, "test_extractor_1"));
|
||||
ASSERT_NO_THROW(test_meta.update(test_model_path_1, test_input_info_1, 2));
|
||||
}
|
||||
|
||||
@ -135,6 +144,7 @@ protected:
|
||||
|
||||
TEST_F(MetaInfoUnitTest, serialize) {
|
||||
std::string seriliazation_path(ov::util::path_join({test_artifacts_dir, "test_meta.meta"}));
|
||||
this->extractors = { "extractor_0", "extractor_1" };
|
||||
this->serialize(seriliazation_path);
|
||||
ASSERT_TRUE(ov::util::file_exists(seriliazation_path));
|
||||
|
||||
@ -170,6 +180,24 @@ TEST_F(MetaInfoUnitTest, serialize) {
|
||||
ASSERT_EQ(input_info[in_xml].ranges.max, max_xml);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto extractors_node = doc.child("meta_info").child("extractors");
|
||||
std::unordered_set<std::string> xml_extractors;
|
||||
for (const auto& in_info_xml : extractors_node.children()) {
|
||||
xml_extractors.insert(std::string(in_info_xml.attribute("name").value()));
|
||||
}
|
||||
ASSERT_EQ(xml_extractors, this->extractors);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MetaInfoUnitTest, read_meta_from_file) {
|
||||
std::string seriliazation_path(ov::util::path_join({test_artifacts_dir, "test_meta.meta"}));
|
||||
this->extractors = { "extractor_0", "extractor_1" };
|
||||
this->serialize(seriliazation_path);
|
||||
auto new_meta = MetaInfo::read_meta_from_file(seriliazation_path);
|
||||
ASSERT_TRUE(this->extractors.count(new_meta.get_any_extractor()));
|
||||
ASSERT_EQ(new_meta.get_input_info(), this->input_info);
|
||||
ASSERT_EQ(new_meta.get_model_info(), this->model_info);
|
||||
}
|
||||
|
||||
TEST_F(MetaInfoUnitTest, update) {
|
||||
@ -185,9 +213,11 @@ TEST_F(MetaInfoUnitTest, update) {
|
||||
ASSERT_EQ(this->model_info[test_model_1].model_paths.size(), 1);
|
||||
ASSERT_EQ(this->model_info[test_model_1].this_op_cnt, 2);
|
||||
test_model_path_1 = ov::util::path_join({ "path", "to", "test", test_model_1 + ".xml"});
|
||||
this->update(test_model_path_1, test_meta_1);
|
||||
this->update(test_model_path_1, test_meta_1, 0, 1, "test_extractor");
|
||||
ASSERT_EQ(this->model_info[test_model_1].model_paths.size(), 2);
|
||||
ASSERT_EQ(this->model_info[test_model_1].this_op_cnt, 3);
|
||||
ASSERT_EQ(this->model_info[test_model_1].this_op_cnt, 3);
|
||||
ASSERT_EQ(this->extractors, std::unordered_set<std::string>({"test_extractor"}));
|
||||
}
|
||||
|
||||
TEST_F(MetaInfoUnitTest, get_model_name_by_path) {
|
||||
@ -204,4 +234,10 @@ TEST_F(MetaInfoUnitTest, get_graph_priority) {
|
||||
ASSERT_TRUE(this->get_graph_priority() >= 0 && this->get_graph_priority() <= 1);
|
||||
}
|
||||
|
||||
TEST_F(MetaInfoUnitTest, get_any_extractor) {
|
||||
auto meta = MetaInfo(test_model_name, test_in_info, 1, 1, "test_extractor");
|
||||
ASSERT_NO_THROW(meta.get_any_extractor());
|
||||
ASSERT_EQ(meta.get_any_extractor(), "test_extractor");
|
||||
}
|
||||
|
||||
} // namespace
|
@ -4,6 +4,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "matchers/subgraph/fused_names.hpp"
|
||||
#include "utils/model.hpp"
|
||||
|
||||
@ -21,50 +23,44 @@ using namespace ov::tools::subgraph_dumper;
|
||||
class FusedNamesExtractorTest : public FusedNamesExtractor,
|
||||
public SubgraphsDumperBaseTest {
|
||||
protected:
|
||||
bool is_match(const std::shared_ptr<ov::Model>& model) {
|
||||
size_t graph_cnt = 0;
|
||||
{
|
||||
auto compiled_names = extract_compiled_model_names(model);
|
||||
std::vector<size_t> op_cnt;
|
||||
for (const auto& op : model->get_ordered_ops()) {
|
||||
if (this->is_node_to_skip(op)) {
|
||||
op_cnt.push_back(1);
|
||||
continue;
|
||||
}
|
||||
auto op_name = op->get_friendly_name();
|
||||
if (!compiled_names.count(op_name)) {
|
||||
op_cnt.push_back(1);
|
||||
} else if (op_cnt.size() > 0) {
|
||||
++op_cnt[op_cnt.size() - 1];
|
||||
}
|
||||
}
|
||||
for (const auto& cnt : op_cnt) {
|
||||
if (cnt > 1) {
|
||||
++graph_cnt;
|
||||
}
|
||||
void is_match(const std::shared_ptr<ov::Model>& model) {
|
||||
auto models_1 = this->extract(model);
|
||||
auto models_2 = this->extract(model);
|
||||
ASSERT_EQ(models_1.size(), models_2.size());
|
||||
auto it_model_1 = models_1.begin();
|
||||
auto it_model_2 = models_2.begin();
|
||||
while (it_model_1 != models_1.end() || it_model_2 != models_2.end()) {
|
||||
SubgraphExtractor extractor;
|
||||
ASSERT_TRUE(extractor.match(std::get<0>(*it_model_1), std::get<0>(*it_model_2)));
|
||||
auto in_info_1 = std::get<1>(*it_model_1);
|
||||
auto in_info_2 = std::get<1>(*it_model_2);
|
||||
for (const auto& in_info : in_info_1) {
|
||||
ASSERT_TRUE(in_info_2.count(in_info.first));
|
||||
ASSERT_EQ(in_info_2[in_info.first], in_info.second);
|
||||
}
|
||||
ASSERT_EQ(std::get<2>(*it_model_1), std::get<2>(*it_model_2));
|
||||
++it_model_1;
|
||||
++it_model_2;
|
||||
}
|
||||
auto models = this->extract(model);
|
||||
return models.size() == graph_cnt;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FusedNamesExtractorTest, extract_0) {
|
||||
auto test_model = Model_0();
|
||||
auto model = test_model.get();
|
||||
ASSERT_TRUE(is_match(model));
|
||||
is_match(model);
|
||||
}
|
||||
|
||||
TEST_F(FusedNamesExtractorTest, extract_1) {
|
||||
auto test_model = Model_1();
|
||||
auto model = test_model.get();
|
||||
ASSERT_TRUE(is_match(model));
|
||||
is_match(model);
|
||||
}
|
||||
|
||||
TEST_F(FusedNamesExtractorTest, extract_2) {
|
||||
auto test_model = Model_2();
|
||||
auto model = test_model.get();
|
||||
ASSERT_TRUE(is_match(model));
|
||||
is_match(model);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -27,6 +27,7 @@ protected:
|
||||
{
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{1, 2});
|
||||
test_parameter->set_friendly_name("test_parameter_0");
|
||||
std::shared_ptr<ov::op::v0::Abs> test_abs =
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter);
|
||||
std::shared_ptr<ov::op::v0::Result> test_res =
|
||||
@ -37,6 +38,7 @@ protected:
|
||||
{
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{2, 5});
|
||||
test_parameter->set_friendly_name("test_parameter_1");
|
||||
std::shared_ptr<ov::op::v0::Abs> test_abs =
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter);
|
||||
std::shared_ptr<ov::op::v0::Result> test_res =
|
||||
@ -86,9 +88,28 @@ TEST_F(ExtractorsManagerTest, match) {
|
||||
ASSERT_FALSE(this->match(test_model_0_1, test_model_1));
|
||||
}
|
||||
|
||||
TEST_F(ExtractorsManagerTest, match_with_in_info) {
|
||||
this->set_extractors(test_map);
|
||||
std::map<std::string, InputInfo> test_in_info({{"test_parameter_0", InputInfo()}}), test_in_info_1({{"test_parameter_1", InputInfo(1, 2, true)}});
|
||||
ASSERT_NO_THROW(this->match(test_model_0_0, test_model_0_1, test_in_info, test_in_info));
|
||||
ASSERT_TRUE(this->match(test_model_0_0, test_model_0_1, test_in_info, test_in_info));
|
||||
ASSERT_NO_THROW(this->match(test_model_0_0, test_model_0_1, test_in_info, test_in_info_1));
|
||||
ASSERT_FALSE(this->match(test_model_0_0, test_model_0_1, test_in_info, test_in_info_1));
|
||||
ASSERT_NO_THROW(this->match(test_model_0_1, test_model_1, test_in_info, test_in_info));
|
||||
ASSERT_FALSE(this->match(test_model_0_1, test_model_1, test_in_info, test_in_info));
|
||||
}
|
||||
|
||||
TEST_F(ExtractorsManagerTest, extract) {
|
||||
this->set_extractors(test_map);
|
||||
ASSERT_NO_THROW(this->extract(test_model_0_0));
|
||||
}
|
||||
|
||||
TEST_F(ExtractorsManagerTest, align_input_info) {
|
||||
std::map<std::string, InputInfo> test_in_info({{"test_parameter_0", InputInfo()}}), test_in_info_ref({{"test_parameter_1", InputInfo()}});
|
||||
ASSERT_NE(test_in_info, test_in_info_ref);
|
||||
ASSERT_NO_THROW(this->align_input_info(test_model_0_0, test_model_0_1, test_in_info, test_in_info_ref));
|
||||
auto c = this->align_input_info(test_model_0_0, test_model_0_1, test_in_info, test_in_info_ref);
|
||||
ASSERT_EQ(c, test_in_info_ref);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -27,7 +27,7 @@ protected:
|
||||
for (const auto& model : models) {
|
||||
bool is_match = false;
|
||||
for (const auto& ref_model : ref_models) {
|
||||
if (this->match(model.first, ref_model)) {
|
||||
if (this->match(std::get<0>(model), ref_model)) {
|
||||
is_match = true;
|
||||
++match_numbers;
|
||||
break;
|
||||
|
@ -5,12 +5,6 @@
|
||||
#include "functional_test_utils/skip_tests_config.hpp"
|
||||
|
||||
std::vector<std::string> disabledTestPatterns() {
|
||||
std::vector<std::string> retVector{
|
||||
// todo: enable these tests with graph cache enabling
|
||||
R"(.*RepeatPatternExtractorTest.*extract_1.*)",
|
||||
R"(.*ModelUtilsTest.*generate_.*)",
|
||||
R"(.*GraphCacheFuncTest.*update_cache.*)",
|
||||
R"(.*FusedNamesExtractorTest.*)",
|
||||
};
|
||||
std::vector<std::string> retVector {};
|
||||
return retVector;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "openvino/op/relu.hpp"
|
||||
#include "openvino/op/parameter.hpp"
|
||||
#include "openvino/op/result.hpp"
|
||||
#include "openvino/op/subtract.hpp"
|
||||
|
||||
class Model_1 {
|
||||
public:
|
||||
@ -23,7 +24,7 @@ public:
|
||||
// | | | |
|
||||
// ------------ ------------
|
||||
// | |
|
||||
// add add param param
|
||||
// add Multiply param param
|
||||
// | | | |
|
||||
// ------------------------------- --------------
|
||||
// | |
|
||||
@ -33,7 +34,7 @@ public:
|
||||
// | |
|
||||
// -------------------------------------------
|
||||
// |
|
||||
// Multiply
|
||||
// subtract
|
||||
// |
|
||||
// result
|
||||
size_t op_idx = 0;
|
||||
@ -82,16 +83,16 @@ public:
|
||||
std::make_shared<ov::op::v0::Clamp>(test_abs_0_1, 0, 10);
|
||||
test_clamp_0_1->set_friendly_name("Op_" + std::to_string(op_idx++));
|
||||
|
||||
std::shared_ptr<ov::op::v1::Add> test_add_0_0 =
|
||||
std::make_shared<ov::op::v1::Add>(test_relu_0_0, test_clamp_0_1);
|
||||
test_add_0_0->set_friendly_name("Op_" + std::to_string(op_idx++));
|
||||
|
||||
std::shared_ptr<ov::op::v1::Multiply> test_multiply_0_0 =
|
||||
std::make_shared<ov::op::v1::Multiply>(test_add_0, test_add_0_0);
|
||||
std::make_shared<ov::op::v1::Multiply>(test_relu_0_0, test_clamp_0_1);
|
||||
test_multiply_0_0->set_friendly_name("Op_" + std::to_string(op_idx++));
|
||||
|
||||
std::shared_ptr<ov::op::v1::Multiply> test_multiply_0_1 =
|
||||
std::make_shared<ov::op::v1::Multiply>(test_add_0, test_multiply_0_0);
|
||||
test_multiply_0_0->set_friendly_name("Op_" + std::to_string(op_idx++));
|
||||
|
||||
std::shared_ptr<ov::op::v0::Relu> test_relu_0_1 =
|
||||
std::make_shared<ov::op::v0::Relu>(test_multiply_0_0);
|
||||
std::make_shared<ov::op::v0::Relu>(test_multiply_0_1);
|
||||
test_relu_0_1->set_friendly_name("Op_" + std::to_string(op_idx++));
|
||||
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_1_0 =
|
||||
@ -107,8 +108,8 @@ public:
|
||||
std::make_shared<ov::op::v0::Relu>(test_multiply_1_1);
|
||||
test_relu_1_1->set_friendly_name("Op_" + std::to_string(op_idx++));
|
||||
|
||||
std::shared_ptr<ov::op::v1::Add> test_add =
|
||||
std::make_shared<ov::op::v1::Add>(test_relu_0_1, test_relu_1_1);
|
||||
std::shared_ptr<ov::op::v1::Subtract> test_add =
|
||||
std::make_shared<ov::op::v1::Subtract>(test_relu_0_1, test_relu_1_1);
|
||||
test_add->set_friendly_name("Op_" + std::to_string(op_idx++));
|
||||
|
||||
std::shared_ptr<ov::op::v0::Result> test_res =
|
||||
@ -142,67 +143,14 @@ public:
|
||||
{
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_0 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{1, 2});
|
||||
std::shared_ptr<ov::op::v0::Abs> test_abs_0 =
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter_0);
|
||||
std::shared_ptr<ov::op::v0::Relu> test_relu_0 =
|
||||
std::make_shared<ov::op::v0::Relu>(test_abs_0);
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_1 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{2, 1});
|
||||
std::shared_ptr<ov::op::v1::Add> test_add =
|
||||
std::make_shared<ov::op::v1::Add>(test_relu_0, test_parameter_1);
|
||||
std::shared_ptr<ov::op::v0::Result> res =
|
||||
std::make_shared<ov::op::v0::Result>(test_add);
|
||||
auto ref_model = std::make_shared<ov::Model>(ov::ResultVector{res},
|
||||
ov::ParameterVector{test_parameter_0, test_parameter_1});
|
||||
ref.push_back(ref_model);
|
||||
}
|
||||
{
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_0 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{1, 2});
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_1 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{1, 2});
|
||||
std::shared_ptr<ov::op::v0::Abs> test_abs_1 =
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter_1);
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter_0);
|
||||
std::shared_ptr<ov::op::v0::Clamp> test_clamp_1 =
|
||||
std::make_shared<ov::op::v0::Clamp>(test_abs_1, 0, 10);
|
||||
std::shared_ptr<ov::op::v0::Result> res =
|
||||
std::make_shared<ov::op::v0::Result>(test_clamp_1);
|
||||
auto ref_model = std::make_shared<ov::Model>(ov::ResultVector{res},
|
||||
ov::ParameterVector{test_parameter_0, test_parameter_1});
|
||||
ref.push_back(ref_model);
|
||||
}
|
||||
{
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_0 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{1, 2});
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_1 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{1, 2});
|
||||
std::shared_ptr<ov::op::v0::Abs> test_abs_1 =
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter_1);
|
||||
std::shared_ptr<ov::op::v0::Clamp> test_clamp_1 =
|
||||
std::make_shared<ov::op::v0::Clamp>(test_abs_1, 0, 10);
|
||||
std::shared_ptr<ov::op::v1::Add> test_add =
|
||||
std::make_shared<ov::op::v1::Add>(test_parameter_0, test_clamp_1);
|
||||
std::shared_ptr<ov::op::v0::Result> res =
|
||||
std::make_shared<ov::op::v0::Result>(test_add);
|
||||
auto ref_model = std::make_shared<ov::Model>(ov::ResultVector{res},
|
||||
ov::ParameterVector{test_parameter_0, test_parameter_1});
|
||||
ref.push_back(ref_model);
|
||||
}
|
||||
{
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_0 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{1, 2});
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_1 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{1, 2});
|
||||
std::shared_ptr<ov::op::v0::Abs> test_abs_1 =
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter_1);
|
||||
std::shared_ptr<ov::op::v0::Clamp> test_clamp_1 =
|
||||
std::make_shared<ov::op::v0::Clamp>(test_abs_1, 0, 10);
|
||||
std::shared_ptr<ov::op::v1::Add> test_add =
|
||||
std::make_shared<ov::op::v1::Add>(test_parameter_0, test_clamp_1);
|
||||
std::shared_ptr<ov::op::v0::Result> res =
|
||||
std::make_shared<ov::op::v0::Result>(test_add);
|
||||
auto ref_model = std::make_shared<ov::Model>(ov::ResultVector{res},
|
||||
ov::ParameterVector{test_parameter_0, test_parameter_1});
|
||||
ov::ParameterVector{test_parameter_0});
|
||||
ref.push_back(ref_model);
|
||||
}
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
std::shared_ptr<ov::op::v0::Parameter> test_parameter_0 =
|
||||
std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{2, 5});
|
||||
std::shared_ptr<ov::op::v0::Abs> test_abs =
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter_0);
|
||||
std::make_shared<ov::op::v0::Abs>(test_parameter);
|
||||
std::shared_ptr<ov::op::v0::Clamp> test_clamp =
|
||||
std::make_shared<ov::op::v0::Clamp>(test_abs, 0, 10);
|
||||
std::shared_ptr<ov::op::v0::Relu> test_relu =
|
||||
|
@ -16,21 +16,13 @@ using namespace ov::tools::subgraph_dumper;
|
||||
|
||||
using ModelUtilsTest = SubgraphsDumperBaseTest;
|
||||
|
||||
std::pair<std::shared_ptr<ov::Node>, std::set<std::shared_ptr<ov::Node>>>
|
||||
std::set<std::shared_ptr<ov::Node>>
|
||||
get_functional_ops(const std::shared_ptr<ov::Model>& model) {
|
||||
std::shared_ptr<ov::Node> start_node = nullptr;
|
||||
std::set<std::shared_ptr<ov::Node>> nodes;
|
||||
|
||||
for (const auto& op : model->get_ordered_ops()) {
|
||||
if (ov::op::util::is_parameter(op) || ov::op::util::is_output(op)) {
|
||||
continue;
|
||||
}
|
||||
if (start_node == nullptr) {
|
||||
start_node = op;
|
||||
}
|
||||
nodes.insert(op);
|
||||
}
|
||||
return { start_node, nodes };
|
||||
return nodes;
|
||||
}
|
||||
|
||||
TEST_F(ModelUtilsTest, generate_0) {
|
||||
@ -39,13 +31,8 @@ TEST_F(ModelUtilsTest, generate_0) {
|
||||
{
|
||||
std::unordered_set<std::string> checked_ops;
|
||||
auto func_ops = get_functional_ops(test_model);
|
||||
auto model_with_in_info = generate_model(func_ops.second, func_ops.first, checked_ops);
|
||||
recovered_model = model_with_in_info.first;
|
||||
for (const auto& op : recovered_model->get_ordered_ops()) {
|
||||
if (ov::op::util::is_parameter(op) || ov::op::util::is_constant(op)) {
|
||||
ASSERT_TRUE(model_with_in_info.second.count(op->get_friendly_name()));
|
||||
}
|
||||
}
|
||||
auto model_with_in_info = generate_model(func_ops, checked_ops, "test_extractor");
|
||||
recovered_model = std::get<0>(model_with_in_info);
|
||||
}
|
||||
{
|
||||
SubgraphExtractor extractor;
|
||||
@ -59,13 +46,8 @@ TEST_F(ModelUtilsTest, generate_1) {
|
||||
{
|
||||
std::unordered_set<std::string> checked_ops;
|
||||
auto func_ops = get_functional_ops(test_model);
|
||||
auto model_with_in_info = generate_model(func_ops.second, func_ops.first, checked_ops);
|
||||
recovered_model = model_with_in_info.first;
|
||||
for (const auto& op : recovered_model->get_ordered_ops()) {
|
||||
if (ov::op::util::is_parameter(op) || ov::op::util::is_constant(op)) {
|
||||
ASSERT_TRUE(model_with_in_info.second.count(op->get_friendly_name()));
|
||||
}
|
||||
}
|
||||
auto model_with_in_info = generate_model(func_ops, checked_ops, "test_extractor");
|
||||
recovered_model = std::get<0>(model_with_in_info);
|
||||
}
|
||||
{
|
||||
SubgraphExtractor extractor;
|
||||
@ -79,13 +61,9 @@ TEST_F(ModelUtilsTest, generate_2) {
|
||||
{
|
||||
std::unordered_set<std::string> checked_ops;
|
||||
auto func_ops = get_functional_ops(test_model);
|
||||
auto model_with_in_info = generate_model(func_ops.second, func_ops.first, checked_ops);
|
||||
recovered_model = model_with_in_info.first;
|
||||
for (const auto& op : recovered_model->get_ordered_ops()) {
|
||||
if (ov::op::util::is_parameter(op) || ov::op::util::is_constant(op)) {
|
||||
ASSERT_TRUE(model_with_in_info.second.count(op->get_friendly_name()));
|
||||
}
|
||||
}
|
||||
auto model_with_in_info = generate_model(func_ops, checked_ops, "extract_model");
|
||||
recovered_model = std::get<0>(model_with_in_info);
|
||||
auto in_info = std::get<1>(model_with_in_info);
|
||||
}
|
||||
{
|
||||
SubgraphExtractor extractor;
|
||||
|
@ -239,6 +239,7 @@ void ReadIRTest::SetUp() {
|
||||
auto it = inputMap.find(next_node->get_type_info());
|
||||
auto tensor = it->second(next_node, function->get_parameter_index(param), param->get_element_type(), param->get_shape());
|
||||
auto const_node = std::make_shared<ov::op::v0::Constant>(tensor);
|
||||
const_node->set_friendly_name(param->get_friendly_name());
|
||||
ov::replace_node(param, const_node);
|
||||
parameter_to_remove.push_back(param);
|
||||
utils::ConstRanges::reset();
|
||||
@ -246,6 +247,11 @@ void ReadIRTest::SetUp() {
|
||||
for (const auto& param : parameter_to_remove) {
|
||||
function->remove_parameter(param);
|
||||
}
|
||||
ov::pass::Manager manager;
|
||||
manager.register_pass<ov::pass::Serialize>("test.xml", "test.bin");
|
||||
manager.run_passes(function);
|
||||
auto b = function->get_parameters();
|
||||
auto c = 0;
|
||||
}
|
||||
|
||||
bool hasDynamic = false;
|
||||
|
@ -958,6 +958,7 @@ InputsMap getInputMap() {
|
||||
#include "openvino/opsets/opset9_tbl.hpp"
|
||||
#include "openvino/opsets/opset10_tbl.hpp"
|
||||
#include "openvino/opsets/opset11_tbl.hpp"
|
||||
#include "openvino/opsets/opset12_tbl.hpp"
|
||||
|
||||
#include "ov_ops/opset_private_tbl.hpp"
|
||||
#undef _OPENVINO_OP_REG
|
||||
|
Loading…
Reference in New Issue
Block a user