Files
openvino/src/core/src/node.cpp
T
Ilya Churaev 554b50eb85 Remove redundant calls from set_argument (#10701)
* Remove redundant calls from set_argument

* Fixed tests
2022-03-03 18:01:59 +03:00

877 lines
30 KiB
C++

// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/node.hpp"
#include <memory>
#include <ngraph/validation_util.hpp>
#include <sstream>
#include <typeindex>
#include <typeinfo>
#include "atomic_guard.hpp"
#include "itt.hpp"
#include "ngraph/graph_util.hpp"
#include "ngraph/op/constant.hpp"
#include "ngraph/op/parameter.hpp"
#include "ngraph/op/result.hpp"
#include "ngraph/pattern/matcher.hpp"
#include "openvino/core/descriptor/input.hpp"
#include "openvino/pass/constant_folding.hpp"
#include "shared_node_info.hpp"
using namespace std;
atomic<size_t> ov::Node::m_next_instance_id(0);
ov::Node::Node(const Node& node)
: m_control_dependents(node.m_control_dependents),
m_control_dependencies(node.m_control_dependencies),
m_instance_id(m_next_instance_id.fetch_add(1)),
m_friendly_name(node.m_friendly_name)
// skip m_unique_name -- will be generated automatically
,
m_inputs(node.m_inputs) // will be modified in the body
// skip m_outputs -- should be initialized outside
,
m_op_annotations(node.m_op_annotations),
m_rt_info(node.m_rt_info) {
// cannot do it without copying node.m_inputs first due to too limiting const qualifiers
for (auto& input : m_inputs) {
input = descriptor::Input(this, input.get_index(), input.get_output());
input.get_output().add_input(&input);
}
}
ov::Node& ov::Node::operator=(const Node& node) {
this->m_control_dependents = node.m_control_dependents;
this->m_control_dependencies = node.m_control_dependencies;
this->m_instance_id = m_next_instance_id.fetch_add(1);
this->m_friendly_name = node.m_friendly_name;
this->m_inputs = node.m_inputs;
this->m_op_annotations = node.m_op_annotations;
this->m_rt_info = node.m_rt_info;
// cannot do it without copying node.m_inputs first due to too limiting const qualifiers
for (auto& input : m_inputs) {
input = descriptor::Input(this, input.get_index(), input.get_output());
input.get_output().add_input(&input);
}
return *this;
}
void ov::Node::insert_info(std::shared_ptr<SharedRTInfo> info) {
std::lock_guard<std::mutex> lock(m_insert_mutex);
m_shared_rt_info.insert(std::move(info));
}
ov::Node::Node(size_t output_size) : Node() {
set_output_size(output_size);
}
ov::Node::Node(const OutputVector& arguments, size_t output_size) : Node() {
set_arguments(arguments);
set_output_size(output_size);
}
ov::Node::~Node() {
try {
// raise a flag to reset nodes cache
for_each(m_shared_rt_info.cbegin(), m_shared_rt_info.cend(), [](const std::shared_ptr<SharedRTInfo>& info) {
info->set_use_topological_cache(false);
});
for (descriptor::Input& input : m_inputs) {
if (input.has_output()) {
// This test adds 1 to the actual count, so a count of 2 means this input is the only
// reference to the node.
if (input.get_output().get_node().use_count() == 2) {
// Don't want to trigger a deep recursive delete
NodeVector nodes{input.get_output().get_node()};
input.remove_output();
safe_delete(nodes, true);
return;
}
input.remove_output();
}
}
} catch (...) {
}
}
std::shared_ptr<ov::Node> ov::Node::copy_with_new_inputs(const OutputVector& inputs) const {
return copy_with_new_inputs(inputs, get_control_dependencies());
}
ov::Output<const ov::Node> ov::Node::get_default_output() const {
return output(get_default_output_index());
}
ov::Output<ov::Node> ov::Node::get_default_output() {
return output(get_default_output_index());
}
size_t ov::Node::get_default_output_index() const {
return 0;
}
size_t ov::Node::no_default_index() const {
NODE_VALIDATION_CHECK(this, false, "Default output not supported");
}
std::shared_ptr<ov::Node> ov::Node::copy_with_new_inputs(
const OutputVector& inputs,
const std::vector<std::shared_ptr<Node>>& control_dependencies) const {
shared_ptr<Node> clone = clone_with_new_inputs(inputs);
for (auto& cdep : control_dependencies) {
clone->add_control_dependency(cdep);
}
for (size_t i = 0; i < get_output_size(); i++) {
clone->get_output_tensor(i).set_names(get_output_tensor(i).get_names());
NGRAPH_SUPPRESS_DEPRECATED_START
clone->get_output_tensor(i).set_name(get_output_tensor(i).get_name());
NGRAPH_SUPPRESS_DEPRECATED_END
}
return clone;
}
void ov::Node::safe_delete(NodeVector& nodes, bool recurse) {
for (auto& input : m_inputs) {
if (input.has_output()) {
// This test adds 1 to the actual count, so a count of 2 means this input is the only
// reference to the node.
auto node = input.get_output().get_node();
if (node.use_count() == 2) {
// Move the node from the input to nodes so we don't trigger a deep recursive delete
nodes.push_back(node);
}
input.remove_output();
}
}
if (recurse) {
while (nodes.size() > 0) {
auto node = nodes.back();
nodes.pop_back();
node->safe_delete(nodes, false);
}
}
}
void ov::Node::set_arguments(const NodeVector& arguments) {
OutputVector outputs;
for (const auto& arg : arguments) {
for (auto& output : arg->outputs()) {
outputs.push_back(output);
}
}
set_arguments(outputs);
}
void ov::Node::set_arguments(const OutputVector& arguments) {
// Remove existing inputs of this node
m_inputs.clear();
// Add this node as a user of each argument.
size_t i = 0;
for (auto& output : arguments) {
set_argument(i++, output);
}
// set_arguments doesn't use replace_output method, so we have to reset cache manually here
for_each(this->m_shared_rt_info.cbegin(), this->m_shared_rt_info.cend(), [](std::shared_ptr<SharedRTInfo> info) {
info->set_use_topological_cache(false);
});
}
ov::descriptor::Input& ov::Node::get_input_descriptor(size_t position) {
while (m_inputs.size() <= position) {
m_inputs.emplace_back(this, m_inputs.size());
}
return m_inputs.at(position);
}
ov::descriptor::Output& ov::Node::get_output_descriptor(size_t position) {
while (m_outputs.size() <= position) {
size_t i = m_outputs.size();
auto tensor_descriptor = make_shared<descriptor::Tensor>(element::dynamic, PartialShape::dynamic(), this, i);
m_outputs.emplace_back(this, i, tensor_descriptor);
}
return m_outputs[position];
}
void ov::Node::set_argument(size_t position, const Output<Node>& argument) {
auto output_node = argument.get_node();
auto& output_descriptor = output_node->m_outputs.size() > argument.get_index()
? output_node->m_outputs.at(argument.get_index())
: output_node->get_output_descriptor(argument.get_index());
if (position < m_inputs.size()) {
get_input_descriptor(position).replace_output(output_descriptor);
} else {
while (m_inputs.size() < position) {
m_inputs.emplace_back(this, m_inputs.size());
}
m_inputs.emplace_back(this, position, output_descriptor);
}
}
void ov::Node::constructor_validate_and_infer_types() {
validate_and_infer_types();
}
void ov::Node::set_output_size(size_t n) {
NGRAPH_CHECK(n >= m_outputs.size(), "shrinking ", m_outputs.size(), " to ", n);
for (size_t i = m_outputs.size(); i < n; ++i) {
// create the descriptors
get_output_descriptor(i);
}
}
void ov::Node::invalidate_values() {
for (const auto& output : outputs())
output.get_tensor().invalidate_values();
}
void ov::Node::validate_and_infer_types() {}
void ov::Node::set_input_is_relevant_to_shape(size_t i, bool relevant) {
NGRAPH_CHECK(i < m_inputs.size(),
"index '",
i,
"' out of range in set_input_is_relevant_to_shape(size_t index, bool relevant)");
m_inputs[i].m_is_relevant_to_shape = relevant;
}
void ov::Node::set_input_is_relevant_to_value(size_t i, bool relevant) {
NGRAPH_CHECK(i < m_inputs.size(),
"index '",
i,
"' out of range in set_input_is_relevant_to_value(size_t index, bool relevant)");
m_inputs[i].m_is_relevant_to_value = relevant;
}
void ov::Node::set_output_type(size_t i, const element::Type& element_type, const PartialShape& pshape) {
OPENVINO_SUPPRESS_DEPRECATED_START
get_output_descriptor(i).get_tensor_ptr()->set_tensor_type(element_type, pshape);
OPENVINO_SUPPRESS_DEPRECATED_END
}
std::string ov::Node::description() const {
return get_type_name();
}
const std::string& ov::Node::get_friendly_name() const {
if (m_friendly_name.empty()) {
return get_name();
}
return m_friendly_name;
}
const std::string& ov::Node::get_name() const {
AtomicGuard lock(m_name_changing);
if (m_unique_name.empty())
m_unique_name = description() + "_" + to_string(m_instance_id);
return m_unique_name;
}
void ov::Node::set_friendly_name(const string& name) {
m_friendly_name = name;
}
ov::Node* ov::Node::get_input_node_ptr(size_t index) const {
NGRAPH_CHECK(index < m_inputs.size(), "index '", index, "' out of range in get_argument(size_t index)");
return m_inputs[index].get_output().get_node().get();
}
std::shared_ptr<ov::Node> ov::Node::get_input_node_shared_ptr(size_t index) const {
NGRAPH_CHECK(index < m_inputs.size(), "index '", index, "' out of range in get_argument(size_t index)");
return m_inputs[index].get_output().get_node();
}
ov::Output<ov::Node> ov::Node::get_input_source_output(size_t i) const {
return input(i).get_source_output();
}
const std::vector<std::shared_ptr<ov::Node>>& ov::Node::get_control_dependencies() const {
return m_control_dependencies;
}
const std::vector<ov::Node*>& ov::Node::get_control_dependents() const {
return m_control_dependents;
}
void ov::Node::add_control_dependency(std::shared_ptr<Node> node) {
if (find(m_control_dependencies.begin(), m_control_dependencies.end(), node) == m_control_dependencies.end()) {
m_control_dependencies.push_back(node);
if (find(node->m_control_dependents.begin(), node->m_control_dependents.end(), this) ==
node->m_control_dependents.end()) {
node->m_control_dependents.push_back(this);
}
}
// control dependency may change the topological order so we have to reset cache
// by setting a flag into shared node info.
for_each(node->m_shared_rt_info.cbegin(), node->m_shared_rt_info.cend(), [](std::shared_ptr<SharedRTInfo> info) {
info->set_use_topological_cache(false);
});
}
void ov::Node::add_node_control_dependencies(std::shared_ptr<Node> source_node) {
for (auto& node : source_node->get_control_dependencies()) {
add_control_dependency(node);
}
}
void ov::Node::add_node_control_dependents(std::shared_ptr<Node> source_node) {
for (Node* node : source_node->get_control_dependents()) {
node->add_control_dependency(shared_from_this());
}
}
void ov::Node::transfer_control_dependents(std::shared_ptr<Node> replacement) {
replacement->add_node_control_dependents(shared_from_this());
clear_control_dependents();
}
void ov::Node::remove_control_dependency(std::shared_ptr<Node> node) {
{
auto it = find(m_control_dependencies.begin(), m_control_dependencies.end(), node);
if (it != m_control_dependencies.end()) {
m_control_dependencies.erase(it);
}
}
{
auto it = find(node->m_control_dependents.begin(), node->m_control_dependents.end(), this);
if (it != node->m_control_dependents.end()) {
node->m_control_dependents.erase(it);
}
}
}
void ov::Node::clear_control_dependencies() {
for (auto& node : m_control_dependencies) {
auto it = find(node->m_control_dependents.begin(), node->m_control_dependents.end(), this);
if (it != node->m_control_dependents.end()) {
node->m_control_dependents.erase(it);
}
}
m_control_dependencies.clear();
}
void ov::Node::clear_control_dependents() {
while (!m_control_dependents.empty()) {
(*m_control_dependents.begin())->remove_control_dependency(shared_from_this());
}
}
const ngraph::op::AutoBroadcastSpec& ov::Node::get_autob() const {
static ngraph::op::AutoBroadcastSpec s_spec;
return s_spec;
}
namespace ov {
ostream& operator<<(ostream& out, const Node& node) {
return node.write_description(out, 1);
}
ostream& operator<<(ostream& out, const Node* node) {
return node->write_description(out, 1);
}
} // namespace ov
std::ostream& ov::Node::write_description(std::ostream& out, uint32_t depth) const {
if (depth == 0) {
out << get_friendly_name();
} else {
out << "v" << get_type_info().version << "::" << get_type_info().name << " " << get_friendly_name() << " (";
string sep = "";
for (const auto& arg : input_values()) {
out << sep << arg;
sep = ", ";
}
out << ") -> (";
sep = "";
for (size_t i = 0; i < get_output_size(); i++) {
out << sep << get_output_element_type(i) << get_output_partial_shape(i);
sep = ", ";
}
out << ")";
}
return out;
}
size_t ov::Node::get_output_size() const {
return m_outputs.size();
}
const ov::element::Type& ov::Node::get_output_element_type(size_t i) const {
NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_element_type(size_t i)");
return m_outputs[i].get_element_type();
}
const ov::element::Type& ov::Node::get_element_type() const {
if (get_output_size() != 1) {
throw ngraph::ngraph_error("get_element_type() must be called on a node with exactly one output.");
}
return get_output_element_type(0);
}
const ov::Shape& ov::Node::get_output_shape(size_t i) const {
NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_shape(size_t i)");
return m_outputs[i].get_shape();
}
const ov::PartialShape& ov::Node::get_output_partial_shape(size_t i) const {
NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_partial_shape(size_t i)");
return m_outputs[i].get_partial_shape();
}
const ov::Shape& ov::Node::get_shape() const {
NODE_VALIDATION_CHECK(this, get_output_size() == 1, "get_shape() must be called on a node with exactly one output");
return get_output_shape(0);
}
std::set<ov::Input<ov::Node>> ov::Node::get_output_target_inputs(size_t i) const {
std::set<Input<Node>> result;
for (auto& input : m_outputs.at(i).get_inputs()) {
result.emplace(input->get_raw_pointer_node(), input->get_index());
}
return result;
}
ov::descriptor::Tensor& ov::Node::get_output_tensor(size_t i) const {
NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_tensor(size_t i)");
return m_outputs[i].get_tensor();
}
ov::descriptor::Tensor& ov::Node::get_input_tensor(size_t i) const {
NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_tensor(size_t i)");
descriptor::Input input = m_inputs[i];
return input.get_tensor();
}
size_t ov::Node::get_input_size() const {
return m_inputs.size();
}
const ov::element::Type& ov::Node::get_input_element_type(size_t i) const {
NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_element_type(size_t i)");
return m_inputs[i].get_element_type();
}
const ov::Shape& ov::Node::get_input_shape(size_t i) const {
NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_shape(size_t i)");
return m_inputs[i].get_shape();
}
const ov::PartialShape& ov::Node::get_input_partial_shape(size_t i) const {
NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_partial_shape(size_t i)");
return m_inputs[i].get_partial_shape();
}
NGRAPH_SUPPRESS_DEPRECATED_START
const string& ov::Node::get_input_tensor_name(size_t i) const {
NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_tensor_name(size_t i)");
return m_inputs[i].get_tensor().get_name();
}
const string& ov::Node::get_output_tensor_name(size_t i) const {
NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_tensor_name(size_t i)");
return m_outputs[i].get_tensor().get_name();
}
NGRAPH_SUPPRESS_DEPRECATED_END
bool ov::Node::has_same_type(std::shared_ptr<const Node> node) const {
if (get_output_size() != node->get_output_size()) {
return false;
}
for (size_t i = 0; i < get_output_size(); ++i) {
if (get_output_element_type(i) != node->get_output_element_type(i) ||
get_output_shape(i) != node->get_output_shape(i)) {
return false;
}
}
return true;
}
ov::NodeVector ov::Node::get_users(bool check_is_used) const {
NodeVector result;
for (const auto& output : outputs()) {
for (auto input : output.get_target_inputs()) {
Node* input_node = input.get_node();
if (!check_is_used || ngraph::is_used(input_node)) {
result.push_back(input_node->shared_from_this());
}
}
}
return result;
}
std::string ov::node_validation_failure_loc_string(const Node* node) {
std::stringstream ss;
ss << "While validating node '" << *node << "' with friendly_name '" << node->get_friendly_name() << '\'';
return ss.str();
}
const std::shared_ptr<ov::Node>& ngraph::check_single_output_arg(const std::shared_ptr<Node>& node, size_t i) {
NGRAPH_CHECK(node->get_output_size() == 1, "Argument ", i, node, " must produce exactly one value.");
return node;
}
const ov::NodeVector& ngraph::check_single_output_args(const NodeVector& args) {
for (size_t i = 0; i < args.size(); ++i) {
ngraph::check_single_output_arg(args.at(i), i);
}
return args;
}
bool ov::Node::match_value(ngraph::pattern::Matcher* matcher,
const Output<Node>& pattern_value,
const Output<Node>& graph_value) {
if (pattern_value.get_index() != graph_value.get_index() ||
(matcher->is_strict_mode() &&
(!pattern_value.get_element_type().compatible(graph_value.get_element_type()) ||
!pattern_value.get_partial_shape().compatible(graph_value.get_partial_shape())))) {
return false;
}
return match_node(matcher, graph_value);
}
bool ov::Node::match_node(ngraph::pattern::Matcher* matcher, const Output<Node>& graph_value) {
matcher->add_node(graph_value);
// Check if a type of a given node, which produces graph_value, matches the type of `this` node
// or `this` node type is an ancestor of that node type. It is not the exact matching, types of
// the nodes
// may not match, but they are connected by the inheritance relation.
// Not exact matching allows using base classes in the patterns and successfully matching such
// patterns
// with sub-graph of descent nodes types.
if (graph_value.get_node_shared_ptr()->get_type_info().is_castable(get_type_info()) &&
matcher->match_arguments(this, graph_value.get_node_shared_ptr())) {
auto& pattern_map = matcher->get_pattern_value_map();
pattern_map[shared_from_this()] = graph_value;
return true;
}
return false;
}
// default implementation for the node to check if it contains partial shape
// we will override this method, for the Op's which depends on additional shape
// attribute to determine if node contains partial shape or not
bool ov::Node::is_dynamic() const {
for (size_t i = 0; i < get_input_size(); i++) {
if (get_input_partial_shape(i).is_dynamic()) {
return true;
}
}
return false;
}
ov::Input<ov::Node> ov::Node::input(size_t input_index) {
if (input_index >= m_inputs.size()) {
throw out_of_range("node input index is out of range");
}
return {this, input_index};
}
ov::Output<ov::Node> ov::Node::input_value(size_t input_index) const {
return input(input_index).get_source_output();
}
ov::Input<const ov::Node> ov::Node::input(size_t input_index) const {
if (input_index >= m_inputs.size()) {
throw out_of_range("node input index is out of range");
}
return {this, input_index};
}
ov::Output<ov::Node> ov::Node::output(size_t output_index) {
// All nodes will have at least 1 output
if (output_index > 0 && output_index >= m_outputs.size()) {
throw out_of_range("node output index is out of range");
}
return Output<Node>(this, output_index);
}
ov::Output<const ov::Node> ov::Node::output(size_t output_index) const {
// All nodes will have at least 1 output
if (output_index > 0 && output_index >= m_outputs.size()) {
throw out_of_range("node output index is out of range");
}
return Output<const Node>(this, output_index);
}
vector<ov::Input<ov::Node>> ov::Node::inputs() {
vector<Input<Node>> result;
for (size_t i = 0; i < get_input_size(); i++) {
result.emplace_back(this, i);
}
return result;
}
vector<ov::Output<ov::Node>> ov::Node::input_values() const {
vector<Output<Node>> result;
for (size_t i = 0; i < get_input_size(); i++) {
result.emplace_back(input(i).get_source_output());
}
return result;
}
vector<ov::Input<const ov::Node>> ov::Node::inputs() const {
vector<Input<const Node>> result;
for (size_t i = 0; i < get_input_size(); i++) {
result.emplace_back(this, i);
}
return result;
}
vector<ov::Output<ov::Node>> ov::Node::outputs() {
vector<Output<Node>> result;
for (size_t i = 0; i < get_output_size(); i++) {
result.emplace_back(shared_from_this(), i);
}
return result;
}
vector<ov::Output<const ov::Node>> ov::Node::outputs() const {
vector<Output<const Node>> result;
for (size_t i = 0; i < get_output_size(); i++) {
result.emplace_back(shared_from_this(), i);
}
return result;
}
bool ov::Node::has_evaluate() const {
return false;
}
OPENVINO_SUPPRESS_DEPRECATED_START
bool ov::Node::evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const {
return false;
}
bool ov::Node::evaluate(const HostTensorVector& output_values,
const HostTensorVector& input_values,
const EvaluationContext& evaluationContext) const {
return evaluate(output_values, input_values);
}
OPENVINO_SUPPRESS_DEPRECATED_END
namespace {
class DynamicTensor : public ngraph::runtime::HostTensor {
private:
ov::Tensor tensor;
public:
DynamicTensor(const ov::element::Type& type) : ngraph::runtime::HostTensor(type, ov::PartialShape::dynamic()) {}
ov::Tensor get_tensor() {
return tensor;
}
protected:
void allocate_buffer() override {
OPENVINO_ASSERT(get_partial_shape().is_static(),
"Attempt to allocate buffer for tensor with partial shape: ",
get_partial_shape());
OPENVINO_ASSERT(get_element_type().is_static(),
"Attempt to allocate buffer for tensor with dynamic type: ",
get_element_type());
m_buffer_size = m_descriptor->size();
tensor = ov::Tensor(get_element_type(), get_partial_shape().get_shape());
m_memory_pointer = tensor.data();
m_aligned_buffer_pool = m_memory_pointer;
}
};
inline ngraph::HostTensorVector create_tmp_tensors(const ov::TensorVector& tensors) {
ngraph::HostTensorVector result;
result.reserve(tensors.size());
for (const auto& tensor : tensors) {
if (!tensor || tensor.get_shape() == ov::Shape{0}) {
auto el_type = ov::element::dynamic;
if (tensor)
el_type = tensor.get_element_type();
// Create dynamic tensor
result.emplace_back(std::make_shared<DynamicTensor>(el_type));
} else {
result.emplace_back(std::make_shared<ngraph::runtime::HostTensor>(tensor.get_element_type(),
tensor.get_shape(),
tensor.data()));
}
}
return std::move(result);
}
inline void update_output_tensors(ov::TensorVector& output_values, const ngraph::HostTensorVector& outputs) {
OPENVINO_ASSERT(output_values.size() == outputs.size());
for (size_t i = 0; i < outputs.size(); i++) {
if (auto dyn_output = std::dynamic_pointer_cast<DynamicTensor>(outputs[i])) {
output_values[i] = dyn_output->get_tensor();
}
}
}
} // namespace
bool ov::Node::evaluate(ov::TensorVector& output_values, const ov::TensorVector& input_values) const {
HostTensorVector output = create_tmp_tensors(output_values);
HostTensorVector input = create_tmp_tensors(input_values);
OPENVINO_SUPPRESS_DEPRECATED_START
bool sts = evaluate(output, input);
OPENVINO_SUPPRESS_DEPRECATED_END
update_output_tensors(output_values, output);
return sts;
}
bool ov::Node::evaluate(ov::TensorVector& output_values,
const ov::TensorVector& input_values,
const ov::EvaluationContext& evaluationContext) const {
HostTensorVector output = create_tmp_tensors(output_values);
HostTensorVector input = create_tmp_tensors(input_values);
OPENVINO_SUPPRESS_DEPRECATED_START
bool sts = evaluate(output, input, evaluationContext);
OPENVINO_SUPPRESS_DEPRECATED_END
update_output_tensors(output_values, output);
return sts;
}
bool ov::Node::evaluate_lower(ov::TensorVector& output_values) const {
HostTensorVector output = create_tmp_tensors(output_values);
OPENVINO_SUPPRESS_DEPRECATED_START
bool sts = evaluate_lower(output);
OPENVINO_SUPPRESS_DEPRECATED_END
update_output_tensors(output_values, output);
return sts;
}
bool ov::Node::evaluate_upper(ov::TensorVector& output_values) const {
HostTensorVector output = create_tmp_tensors(output_values);
OPENVINO_SUPPRESS_DEPRECATED_START
bool sts = evaluate_upper(output);
OPENVINO_SUPPRESS_DEPRECATED_END
update_output_tensors(output_values, output);
return sts;
}
OPENVINO_SUPPRESS_DEPRECATED_START
bool ov::Node::evaluate_lower(const HostTensorVector& output_values) const {
const auto& inputs = input_values();
bool dyn_inputs = std::any_of(inputs.begin(), inputs.end(), [](const Output<Node>& output) {
return !output.get_tensor().has_and_set_bound();
});
if (dyn_inputs)
return false;
return ngraph::default_lower_bound_evaluator(this, output_values);
}
bool ov::Node::evaluate_upper(const HostTensorVector& output_values) const {
const auto& inputs = input_values();
bool dyn_inputs = std::any_of(inputs.begin(), inputs.end(), [](const Output<Node>& output) {
return !output.get_tensor().has_and_set_bound();
});
if (dyn_inputs)
return false;
return ngraph::default_upper_bound_evaluator(this, output_values);
}
OPENVINO_SUPPRESS_DEPRECATED_END
bool ov::Node::evaluate_label(TensorLabelVector& output_labels) const {
return false;
}
bool ov::Node::constant_fold(OutputVector& output_values, const OutputVector& input_values) {
OV_ITT_SCOPED_TASK(ov::itt::domains::nGraph, "Node::constant_fold");
if (m_rt_info.count(ov::pass::DisableConstantFolding::get_type_info_static())) {
return false;
}
// If all the inputs are constants, try to evaluate the outputs
bool all_constants = std::all_of(input_values.begin(), input_values.end(), [](const Output<Node>& input) {
return ov::as_type_ptr<ngraph::op::v0::Constant>(input.get_node_shared_ptr());
});
if (!all_constants)
return false;
HostTensorVector input_tensors;
for (const auto& input : input_values) {
auto host_tensor = make_shared<ngraph::runtime::HostTensor>(
ov::as_type_ptr<ngraph::op::v0::Constant>(input.get_node_shared_ptr()));
input_tensors.push_back(host_tensor);
}
HostTensorVector output_tensors;
OutputVector output_constants;
for (const auto& output : outputs()) {
auto tensor = make_shared<HostTensor>(output.get_element_type(), output.get_partial_shape());
output_tensors.push_back(tensor);
}
OPENVINO_SUPPRESS_DEPRECATED_START
if (evaluate(output_tensors, input_tensors)) {
for (size_t i = 0; i < output_tensors.size(); ++i) {
output_values[i] = make_shared<ngraph::op::Constant>(output_tensors[i]);
}
return true;
}
OPENVINO_SUPPRESS_DEPRECATED_END
return false;
}
namespace ov {
BWDCMP_RTTI_DEFINITION(AttributeAdapter<shared_ptr<Node>>);
AttributeAdapter<std::shared_ptr<Node>>::AttributeAdapter(std::shared_ptr<Node>& value) : m_ref(value) {}
bool AttributeAdapter<std::shared_ptr<Node>>::visit_attributes(AttributeVisitor& visitor) {
auto original_id = visitor.get_registered_node_id(m_ref);
auto id = original_id;
visitor.on_attribute("ID", id);
if (id != original_id) {
m_ref = visitor.get_registered_node(id);
}
return true;
}
BWDCMP_RTTI_DEFINITION(AttributeAdapter<NodeVector>);
AttributeAdapter<NodeVector>::AttributeAdapter(NodeVector& ref) : m_ref(ref) {}
bool AttributeAdapter<NodeVector>::visit_attributes(AttributeVisitor& visitor) {
size_t size = m_ref.size();
visitor.on_attribute("size", size);
if (size != m_ref.size()) {
m_ref.resize(size);
}
ostringstream index;
for (size_t i = 0; i < size; i++) {
index.str("");
index << i;
string id;
if (m_ref[i]) {
id = visitor.get_registered_node_id(m_ref[i]);
}
visitor.on_attribute(index.str(), id);
if (!m_ref[i]) {
m_ref[i] = visitor.get_registered_node(id);
}
}
return true;
}
} // namespace ov