Enabled importing ONNX Yolo v3, added Loop op (#957)
This commit is contained in:
parent
3a9db885bf
commit
d9076c29a2
@ -28,6 +28,8 @@ add_library(onnx_importer SHARED
|
||||
core/attribute.hpp
|
||||
core/graph.cpp
|
||||
core/graph.hpp
|
||||
core/graph_cache.cpp
|
||||
core/graph_cache.hpp
|
||||
core/model.cpp
|
||||
core/model.hpp
|
||||
core/node.hpp
|
||||
@ -126,6 +128,8 @@ add_library(onnx_importer SHARED
|
||||
op/log.hpp
|
||||
op/log_softmax.cpp
|
||||
op/log_softmax.hpp
|
||||
op/loop.cpp
|
||||
op/loop.hpp
|
||||
op/lp_norm.cpp
|
||||
op/lp_norm.hpp
|
||||
op/lp_pool.cpp
|
||||
@ -249,6 +253,8 @@ add_library(onnx_importer SHARED
|
||||
utils/pooling_factory.hpp
|
||||
utils/recurrent.cpp
|
||||
utils/recurrent.hpp
|
||||
utils/provenance_tag.cpp
|
||||
utils/provenance_tag.hpp
|
||||
utils/reduction.cpp
|
||||
utils/reduction.hpp
|
||||
utils/reshape.cpp
|
||||
|
@ -32,9 +32,22 @@ namespace ngraph
|
||||
return result;
|
||||
}
|
||||
|
||||
Graph Attribute::get_graph(Model& model) const
|
||||
Subgraph Attribute::get_subgraph(const Graph& parent_graph) const
|
||||
{
|
||||
return Graph{m_attribute_proto->g(), model};
|
||||
if (m_attribute_proto->type() != ONNX_NAMESPACE::AttributeProto_AttributeType_GRAPH)
|
||||
{
|
||||
throw error::attribute::InvalidData{m_attribute_proto->type()};
|
||||
}
|
||||
|
||||
ONNX_NAMESPACE::ModelProto model_proto;
|
||||
const auto& graph = m_attribute_proto->g();
|
||||
*(model_proto.mutable_graph()) = graph;
|
||||
// We're creating here a model with unset `opset_import` field. This shouldn't
|
||||
// be a problem, since we add ONNX opset as a default available opset. Moreover
|
||||
// if we encounter a node absent in current available opsets we will try
|
||||
// to add it's domain to available opsets.
|
||||
Model model{model_proto};
|
||||
return Subgraph{graph, model, parent_graph};
|
||||
}
|
||||
|
||||
} // namespace onnx_import
|
||||
|
@ -27,6 +27,7 @@ namespace ngraph
|
||||
{
|
||||
// forward declarations
|
||||
class Graph;
|
||||
class Subgraph;
|
||||
class Model;
|
||||
|
||||
// Detecting automatically the underlying type used to store the information
|
||||
@ -285,7 +286,7 @@ namespace ngraph
|
||||
float get_float() const { return m_attribute_proto->f(); }
|
||||
int64_t get_integer() const { return m_attribute_proto->i(); }
|
||||
const std::string& get_string() const { return m_attribute_proto->s(); }
|
||||
Graph get_graph(Model&) const;
|
||||
Subgraph get_subgraph(const Graph& parent_graph) const;
|
||||
|
||||
std::vector<Tensor> get_tensor_array() const
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "node.hpp"
|
||||
#include "provenance.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/provenance_tag.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
@ -61,55 +62,33 @@ namespace ngraph
|
||||
std::string domain = get_node_domain(node_proto);
|
||||
return (domain.empty() ? "" : domain + ".") + node_proto.op_type();
|
||||
}
|
||||
|
||||
static std::string concat_strings(
|
||||
const std::vector<std::reference_wrapper<const std::string>>& strings)
|
||||
{
|
||||
const auto concat_with_comma =
|
||||
[](const std::string& accumulator,
|
||||
std::reference_wrapper<const std::string> next_string) {
|
||||
return accumulator + ", " + next_string.get();
|
||||
};
|
||||
|
||||
return std::accumulate(
|
||||
strings.begin() + 1, strings.end(), strings.begin()->get(), concat_with_comma);
|
||||
}
|
||||
|
||||
static std::string build_input_provenance_tag(const std::string& input_name,
|
||||
const PartialShape& shape)
|
||||
{
|
||||
std::stringstream tag_builder;
|
||||
tag_builder << "<ONNX Input (" << input_name << ") Shape:" << shape << ">";
|
||||
return tag_builder.str();
|
||||
}
|
||||
|
||||
static std::string build_op_provenance_tag(const Node& onnx_node)
|
||||
{
|
||||
const auto output_names = concat_strings(onnx_node.get_output_names());
|
||||
const auto node_name =
|
||||
onnx_node.get_name().empty() ? "" : onnx_node.get_name() + " ";
|
||||
|
||||
return std::string{"<ONNX " + onnx_node.op_type() + " (" + node_name + "-> " +
|
||||
output_names + ")>"};
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
Graph::Graph(const ONNX_NAMESPACE::GraphProto& graph_proto, Model& model)
|
||||
: Graph(graph_proto, model, std::unique_ptr<GraphCache>(new GraphCache()))
|
||||
{
|
||||
}
|
||||
|
||||
Graph::Graph(const ONNX_NAMESPACE::GraphProto& graph_proto,
|
||||
Model& model,
|
||||
std::unique_ptr<GraphCache>&& cache)
|
||||
: m_graph_proto{&graph_proto}
|
||||
, m_model{&model}
|
||||
, m_cache{std::move(cache)}
|
||||
{
|
||||
std::map<std::string, Tensor> initializers;
|
||||
// Process all initializers in the graph
|
||||
for (const auto& initializer_tensor : m_graph_proto->initializer())
|
||||
{
|
||||
if (initializer_tensor.has_name())
|
||||
{
|
||||
Tensor tensor = Tensor{initializer_tensor};
|
||||
m_initializers.emplace(initializer_tensor.name(), tensor);
|
||||
initializers.emplace(initializer_tensor.name(), tensor);
|
||||
|
||||
// For each initializer, create a Constant node and store in cache
|
||||
// For each initializer create a Constant node and store it in cache
|
||||
auto ng_constant = tensor.get_ng_constant();
|
||||
add_provenance_tag_to_initializer(tensor, ng_constant);
|
||||
m_ng_node_cache.emplace(initializer_tensor.name(), std::move(ng_constant));
|
||||
m_cache->emplace_node(initializer_tensor.name(), std::move(ng_constant));
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,15 +98,15 @@ namespace ngraph
|
||||
m_inputs.emplace_back(input);
|
||||
|
||||
// Check if a Constant node was already created from an initializer
|
||||
if (m_ng_node_cache.count(input.name()) > 0)
|
||||
if (m_cache->contains(input.name()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto value_info = m_inputs.back();
|
||||
auto ng_node = value_info.get_ng_node(m_parameters, m_initializers);
|
||||
auto ng_node = value_info.get_ng_node(m_parameters, initializers);
|
||||
add_provenance_tag_to_input(value_info, ng_node);
|
||||
m_ng_node_cache[input.name()] = std::move(ng_node);
|
||||
m_cache->emplace_node(input.name(), std::move(ng_node));
|
||||
}
|
||||
|
||||
// Process all graph outputs
|
||||
@ -181,11 +160,22 @@ namespace ngraph
|
||||
// https://github.com/onnx/onnx/blob/master/docs/IR.md#optional-inputs-and-outputs
|
||||
for (std::size_t i{0}; i < node.get_outputs_size(); ++i)
|
||||
{
|
||||
m_ng_node_cache[node.output(i)] = ng_nodes.at(i);
|
||||
m_cache->emplace_node(node.output(i), std::move(ng_nodes.at(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const GraphCache& Graph::get_graph_cache() const { return *m_cache.get(); }
|
||||
bool Graph::is_node_in_cache(const std::string& name) const
|
||||
{
|
||||
return m_cache->contains(name);
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Node> Graph::get_ng_node_from_cache(const std::string& name) const
|
||||
{
|
||||
return m_cache->get_node(name);
|
||||
}
|
||||
|
||||
NodeVector Graph::get_ng_outputs() const
|
||||
{
|
||||
NodeVector results;
|
||||
@ -268,6 +258,17 @@ namespace ngraph
|
||||
[&tag](std::shared_ptr<ngraph::Node> ng_node) { ng_node->add_provenance_tag(tag); },
|
||||
ng_inputs);
|
||||
}
|
||||
|
||||
Subgraph::Subgraph(const ONNX_NAMESPACE::GraphProto& proto,
|
||||
Model& model,
|
||||
const Graph& parent_graph)
|
||||
: Graph(
|
||||
proto,
|
||||
model,
|
||||
std::unique_ptr<SubgraphCache>(new SubgraphCache(parent_graph.get_graph_cache())))
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace onnx_import
|
||||
|
||||
} // namespace ngraph
|
||||
|
@ -16,11 +16,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <onnx/onnx_pb.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "default_opset.hpp"
|
||||
#include "graph_cache.hpp"
|
||||
#include "model.hpp"
|
||||
#include "ngraph/op/parameter.hpp"
|
||||
#include "operator_set.hpp"
|
||||
@ -39,14 +41,17 @@ namespace ngraph
|
||||
const std::vector<ValueInfo>& get_outputs() const { return m_outputs; }
|
||||
NodeVector get_ng_outputs() const;
|
||||
const ParameterVector& get_ng_parameters() const { return m_parameters; }
|
||||
std::shared_ptr<ngraph::Node> get_ng_node_from_cache(const std::string& name) const
|
||||
{
|
||||
return m_ng_node_cache.at(name);
|
||||
}
|
||||
bool is_node_in_cache(const std::string& name) const;
|
||||
std::shared_ptr<ngraph::Node> get_ng_node_from_cache(const std::string& name) const;
|
||||
const std::string& get_name() const { return m_graph_proto->name(); }
|
||||
NodeVector make_ng_nodes(const Node& onnx_node) const;
|
||||
const GraphCache& get_graph_cache() const;
|
||||
|
||||
protected:
|
||||
Graph(const ONNX_NAMESPACE::GraphProto& proto,
|
||||
Model& model,
|
||||
std::unique_ptr<GraphCache>&& cache);
|
||||
|
||||
void set_friendly_names(const Node& onnx_node, const NodeVector& ng_node_vector) const;
|
||||
|
||||
void add_provenance_tag_to_initializer(
|
||||
@ -59,15 +64,30 @@ namespace ngraph
|
||||
|
||||
private:
|
||||
const ONNX_NAMESPACE::GraphProto* m_graph_proto;
|
||||
std::unique_ptr<GraphCache> m_cache;
|
||||
std::vector<Node> m_nodes;
|
||||
std::vector<ValueInfo> m_inputs;
|
||||
std::vector<ValueInfo> m_outputs;
|
||||
ParameterVector m_parameters;
|
||||
std::map<std::string, std::shared_ptr<ngraph::Node>> m_ng_node_cache;
|
||||
std::map<std::string, Tensor> m_initializers;
|
||||
Model* m_model;
|
||||
};
|
||||
|
||||
/// \brief Representation of ONNX subgraph. It is used for example by ONNX Loop op.
|
||||
/// It has access for initializers both from subgraph and from parent graph
|
||||
/// cache.
|
||||
class Subgraph : public Graph
|
||||
{
|
||||
public:
|
||||
/// \brief Subgraph a GraphCache class object.
|
||||
///
|
||||
/// \param[in] proto The ONNX protobuf graph representation.
|
||||
/// \param[in] model The ONNX model object.
|
||||
/// \param[in] parent_graph The reference to the parent graph.
|
||||
Subgraph(const ONNX_NAMESPACE::GraphProto& proto,
|
||||
Model& model,
|
||||
const Graph& parent_graph);
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& outs, const Graph& graph)
|
||||
{
|
||||
return (outs << "<Graph: " << graph.get_name() << ">");
|
||||
|
75
ngraph/src/ngraph/frontend/onnx_import/core/graph_cache.cpp
Normal file
75
ngraph/src/ngraph/frontend/onnx_import/core/graph_cache.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
|
||||
#include "graph_cache.hpp"
|
||||
#include "except.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace onnx_import
|
||||
{
|
||||
void GraphCache::emplace_node(const std::string& name, std::shared_ptr<ngraph::Node>&& node)
|
||||
{
|
||||
m_graph_cache_map[name] = std::move(node);
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Node> GraphCache::get_node(const std::string& name) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_graph_cache_map.at(name);
|
||||
}
|
||||
catch (const std::out_of_range&)
|
||||
{
|
||||
throw ngraph_error(name + " node not found in graph cache");
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphCache::contains(const std::string& name) const
|
||||
{
|
||||
return (m_graph_cache_map.count(name) > 0);
|
||||
}
|
||||
|
||||
SubgraphCache::SubgraphCache(const GraphCache& parent_graph_cache)
|
||||
: m_parent_graph_cache{&parent_graph_cache}
|
||||
{
|
||||
if (m_parent_graph_cache == nullptr)
|
||||
{
|
||||
throw ngraph_error("Parent graph cache is not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Node> SubgraphCache::get_node(const std::string& name) const
|
||||
{
|
||||
// present in subgraph scope
|
||||
if (GraphCache::contains(name))
|
||||
{
|
||||
return GraphCache::get_node(name);
|
||||
}
|
||||
else // present in parent graph scope
|
||||
{
|
||||
return m_parent_graph_cache->get_node(name);
|
||||
}
|
||||
}
|
||||
|
||||
bool SubgraphCache::contains(const std::string& name) const
|
||||
{
|
||||
// the node is in subgraph or in parent graph scope
|
||||
return GraphCache::contains(name) || m_parent_graph_cache->contains(name);
|
||||
}
|
||||
|
||||
} // namespace onnx_import
|
||||
} // namespace ngraph
|
90
ngraph/src/ngraph/frontend/onnx_import/core/graph_cache.hpp
Normal file
90
ngraph/src/ngraph/frontend/onnx_import/core/graph_cache.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "ngraph/node.hpp"
|
||||
namespace ngraph
|
||||
{
|
||||
namespace onnx_import
|
||||
{
|
||||
/// \brief GraphCache stores and provides access to ONNX graph initializers.
|
||||
class GraphCache
|
||||
{
|
||||
public:
|
||||
/// \brief Add node to the cache or override the existing one.
|
||||
///
|
||||
/// \note GraphCahce takes ownership of the node.
|
||||
///
|
||||
/// \param[in] name The name of node added to the cache.
|
||||
/// \param[in] node The node added to the cache.
|
||||
void emplace_node(const std::string& name, std::shared_ptr<ngraph::Node>&& node);
|
||||
|
||||
/// \brief Get the node from the cache
|
||||
///
|
||||
/// \note If the node is not found the ngraph_error exception is thrown.
|
||||
///
|
||||
/// \param[in] name The name of the node.
|
||||
///
|
||||
/// \return The node named `name`.
|
||||
virtual std::shared_ptr<ngraph::Node> get_node(const std::string& name) const;
|
||||
|
||||
/// \brief Return true if the node named `name` exist in the cache.
|
||||
///
|
||||
/// \param[in] name The name of the node.
|
||||
///
|
||||
/// \return true if the node named `name` exist in the cache, false otherwise.
|
||||
virtual bool contains(const std::string& name) const;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::shared_ptr<ngraph::Node>> m_graph_cache_map;
|
||||
};
|
||||
|
||||
class SubgraphCache : public GraphCache
|
||||
{
|
||||
public:
|
||||
/// \brief Constructs a SubgraphCache class object.
|
||||
///
|
||||
/// \param[in] parent_graph_cache The reference to the parent graph.
|
||||
SubgraphCache(const GraphCache& parent_graph_cache);
|
||||
|
||||
/// \brief Get the node from the cache (subgraph or parent graph)
|
||||
///
|
||||
/// \note If the node is not found the ngraph_error exception is thrown.
|
||||
///
|
||||
/// \param[in] name The name of the node.
|
||||
///
|
||||
/// \return The node named `name` from subgraph (as present) or from parent graph.
|
||||
std::shared_ptr<ngraph::Node> get_node(const std::string& name) const override;
|
||||
|
||||
/// \brief Return true if the node named `name` exist in the cache.
|
||||
///
|
||||
/// \param[in] name The name of the node.
|
||||
///
|
||||
/// \return true if the node named `name` exist in the cache
|
||||
/// (subgraph or parent graph), false otherwise.
|
||||
bool contains(const std::string& name) const override;
|
||||
|
||||
private:
|
||||
const GraphCache* m_parent_graph_cache;
|
||||
};
|
||||
|
||||
} // namespace onnx_import
|
||||
} // namespace ngraph
|
@ -126,6 +126,20 @@ namespace ngraph
|
||||
return it->template get_value<T>();
|
||||
}
|
||||
|
||||
template <>
|
||||
Subgraph Node::Impl::get_attribute_value(const std::string& name) const
|
||||
{
|
||||
auto it = std::find_if(
|
||||
std::begin(m_attributes), std::end(m_attributes), [&](const Attribute& attribute) {
|
||||
return attribute.get_name() == name;
|
||||
});
|
||||
if (it == std::end(m_attributes))
|
||||
{
|
||||
throw error::node::UnknownAttribute{this->name(), name};
|
||||
}
|
||||
return it->get_subgraph(graph());
|
||||
}
|
||||
|
||||
NodeVector Node::Impl::get_ng_nodes(const Node& node) const
|
||||
{
|
||||
return m_graph->make_ng_nodes(node);
|
||||
@ -336,9 +350,9 @@ namespace ngraph
|
||||
}
|
||||
|
||||
template <>
|
||||
Graph Node::get_attribute_value(const std::string& name) const
|
||||
Subgraph Node::get_attribute_value(const std::string& name) const
|
||||
{
|
||||
return m_pimpl->template get_attribute_value<Graph>(name);
|
||||
return m_pimpl->template get_attribute_value<Subgraph>(name);
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <onnx/onnx_pb.h>
|
||||
|
||||
#include "default_opset.hpp"
|
||||
#include "ngraph/op/constant.hpp"
|
||||
#include "ngraph/op/parameter.hpp"
|
||||
#include "ngraph/partial_shape.hpp"
|
||||
#include "ngraph/type/element_type.hpp"
|
||||
#include "node.hpp"
|
||||
@ -97,14 +99,15 @@ namespace ngraph
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<op::Parameter> get_ng_parameter() const
|
||||
std::shared_ptr<ngraph::op::Parameter> get_ng_parameter() const
|
||||
{
|
||||
auto parameter = std::make_shared<op::Parameter>(get_element_type(), get_shape());
|
||||
auto parameter =
|
||||
std::make_shared<ngraph::op::Parameter>(get_element_type(), get_shape());
|
||||
parameter->set_friendly_name(get_name());
|
||||
return parameter;
|
||||
}
|
||||
|
||||
std::shared_ptr<op::Constant> get_ng_constant(const Tensor& tensor) const
|
||||
std::shared_ptr<ngraph::op::Constant> get_ng_constant(const Tensor& tensor) const
|
||||
{
|
||||
return tensor.get_ng_constant();
|
||||
}
|
||||
|
@ -33,7 +33,14 @@ namespace ngraph
|
||||
inline NodeVector identity(const Node& node)
|
||||
{
|
||||
auto input = node.get_ng_inputs().at(0);
|
||||
auto zero = default_opset::Constant::create(input->get_element_type(), {}, {0});
|
||||
if (input->get_element_type() == ngraph::element::boolean)
|
||||
{
|
||||
const auto logic_zero =
|
||||
default_opset::Constant::create(ngraph::element::boolean, {}, {false});
|
||||
return {std::make_shared<default_opset::LogicalOr>(input, logic_zero)};
|
||||
}
|
||||
const auto zero =
|
||||
default_opset::Constant::create(input->get_element_type(), {}, {0});
|
||||
return {std::make_shared<default_opset::Add>(input, zero)};
|
||||
}
|
||||
} // namespace set_1
|
||||
|
204
ngraph/src/ngraph/frontend/onnx_import/op/loop.cpp
Normal file
204
ngraph/src/ngraph/frontend/onnx_import/op/loop.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
#include "loop.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#include "core/graph.hpp"
|
||||
#include "default_opset.hpp"
|
||||
#include "exceptions.hpp"
|
||||
#include "ngraph/function.hpp"
|
||||
#include "utils/reshape.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace onnx_import
|
||||
{
|
||||
namespace op
|
||||
{
|
||||
namespace set_1
|
||||
{
|
||||
namespace
|
||||
{
|
||||
/// \brief The termination condition input is not supported by
|
||||
/// TensorIterator now. If it is possible to determine
|
||||
// that termination condition is always true,
|
||||
// it can be ignored and execute using current version
|
||||
// of TensorIterator.
|
||||
///
|
||||
/// \param[in] loop_cond Termination loop condition input of Loop
|
||||
/// operator (initial value).
|
||||
/// \param[in] body_cond Termination loop condition input of the body of
|
||||
/// the Loop (value updated during Loop iterations).
|
||||
///
|
||||
/// \return true if termination condition is true and it cannot be changed
|
||||
/// during Loop iterations, false otherwise.
|
||||
bool is_termination_condition_always_true(
|
||||
const std::shared_ptr<ngraph::Node>& loop_cond,
|
||||
const std::shared_ptr<ngraph::Node>& body_cond)
|
||||
{
|
||||
bool loop_cond_value = false;
|
||||
if (loop_cond->is_constant() &&
|
||||
loop_cond->get_element_type() == element::boolean)
|
||||
{
|
||||
loop_cond_value = as_type_ptr<default_opset::Constant>(loop_cond)
|
||||
->cast_vector<bool>()
|
||||
.at(0);
|
||||
}
|
||||
// According to ONNX skipped cond input (is_null) means
|
||||
// that is has true value
|
||||
bool is_loop_cond_true = loop_cond->is_null() || loop_cond_value == true;
|
||||
|
||||
if (!is_loop_cond_true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If body termination condition input matches Indentity op pattern the has
|
||||
// value of loop_cond - true
|
||||
// Identity op for boolean value is represented by LogicalOr op whose second
|
||||
// input is always false
|
||||
if (is_type<default_opset::LogicalOr>(body_cond))
|
||||
{
|
||||
const auto second_input =
|
||||
body_cond->input_value(1).get_node_shared_ptr();
|
||||
if (second_input->is_constant() &&
|
||||
second_input->get_element_type() == element::boolean &&
|
||||
as_type_ptr<default_opset::Constant>(second_input)
|
||||
->cast_vector<bool>()
|
||||
.at(0) == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NodeVector loop(const Node& node)
|
||||
{
|
||||
const auto& ng_inputs = node.get_ng_inputs();
|
||||
// optional inputs
|
||||
const std::shared_ptr<ngraph::Node> trip_count = ng_inputs.at(0);
|
||||
const std::shared_ptr<ngraph::Node> loop_cond = ng_inputs.at(1);
|
||||
|
||||
// At this moment nGraph TensorIterator doesn't have support for conditional
|
||||
// termination of iterations.
|
||||
CHECK_VALID_NODE(node,
|
||||
!trip_count->is_null(),
|
||||
"Currently nGraph requires trip count input to be provided.");
|
||||
|
||||
const OutputVector loop_carried_dependencies{std::next(ng_inputs.begin(), 2),
|
||||
ng_inputs.end()};
|
||||
|
||||
// required
|
||||
const Subgraph& body_graph{node.get_attribute_value<Subgraph>("body")};
|
||||
const auto& graph_outputs =
|
||||
ngraph::as_output_vector(body_graph.get_ng_outputs());
|
||||
const auto& graph_inputs = body_graph.get_ng_parameters();
|
||||
|
||||
CHECK_VALID_NODE(
|
||||
node,
|
||||
graph_inputs.size() == loop_carried_dependencies.size() + 2,
|
||||
"The provided loop body graph inputs size (",
|
||||
graph_inputs.size(),
|
||||
"), is not equal to the sum of loop carried dependencies and two mandatory"
|
||||
" inputs (",
|
||||
loop_carried_dependencies.size() + 2,
|
||||
")");
|
||||
|
||||
CHECK_VALID_NODE(node,
|
||||
graph_outputs.size() >= loop_carried_dependencies.size() + 1,
|
||||
"The provided loop body graph outputs size (",
|
||||
graph_outputs.size(),
|
||||
") has to small number of outpus. Required at least: ",
|
||||
loop_carried_dependencies.size() + 1);
|
||||
|
||||
const auto& body_loop_cond = graph_outputs.at(0).get_node_shared_ptr();
|
||||
CHECK_VALID_NODE(
|
||||
node,
|
||||
is_termination_condition_always_true(loop_cond, body_loop_cond),
|
||||
"Given termination loop condition input is not supported by Loop operator");
|
||||
|
||||
// TODO: Remove when loop condition would be supported.
|
||||
const auto& cond_node =
|
||||
default_opset::Constant::create(element::boolean, Shape{}, {true});
|
||||
|
||||
// create the loop body
|
||||
const auto body = std::make_shared<ngraph::op::TensorIterator::BodyLambda>(
|
||||
graph_outputs, graph_inputs);
|
||||
auto tensor_iterator = std::make_shared<ngraph::op::TensorIterator>();
|
||||
tensor_iterator->set_body(body);
|
||||
|
||||
// TensorIterator need to iterate over some input, thus we have to create
|
||||
// 1 dim tensor with number of values equal to value provided by trip_count
|
||||
// input.
|
||||
const auto loop_trip_count = std::make_shared<default_opset::Range>(
|
||||
default_opset::Constant::create(
|
||||
trip_count->get_element_type(), Shape{}, {0}),
|
||||
ngraph::onnx_import::reshape::interpret_as_scalar(trip_count),
|
||||
default_opset::Constant::create(
|
||||
trip_count->get_element_type(), Shape{}, {1}));
|
||||
|
||||
// We iterate over trip_count input.
|
||||
// start=0, stride=1, part_size=1, end=-1, axis=0
|
||||
tensor_iterator->set_sliced_input(
|
||||
graph_inputs.at(0), loop_trip_count, 0, 1, 1, -1, 0);
|
||||
|
||||
// Set loop condition input, which should be changing over the iterations.
|
||||
tensor_iterator->set_merged_input(
|
||||
graph_inputs.at(1), cond_node, graph_outputs.at(0));
|
||||
|
||||
// Setting up other Loop body inputs.
|
||||
auto graph_inputs_it = std::next(graph_inputs.begin(), 2);
|
||||
auto graph_outputs_it = std::next(graph_outputs.begin(), 1);
|
||||
|
||||
// Set-up loop carried dependencies and final output values
|
||||
OutputVector final_values;
|
||||
for (const auto& dep : loop_carried_dependencies)
|
||||
{
|
||||
tensor_iterator->set_merged_input(
|
||||
*graph_inputs_it++, dep, *graph_outputs_it);
|
||||
final_values.push_back(
|
||||
tensor_iterator->get_iter_value(*graph_outputs_it++, -1));
|
||||
}
|
||||
|
||||
// Set-up scan outputs
|
||||
OutputVector scan_outputs;
|
||||
for (; graph_outputs_it != graph_outputs.end(); graph_outputs_it++)
|
||||
{
|
||||
// TODO: does concatenating along 0 axis is right?
|
||||
// start=0, stride=1, part_size=1, end=-1, axis=0
|
||||
scan_outputs.push_back(tensor_iterator->get_concatenated_slices(
|
||||
*graph_outputs_it, 0, 1, 1, -1, 0));
|
||||
}
|
||||
|
||||
NodeVector node_outputs;
|
||||
for (const auto& v : final_values)
|
||||
{
|
||||
node_outputs.push_back(v.as_single_output_node());
|
||||
}
|
||||
for (const auto& v : scan_outputs)
|
||||
{
|
||||
node_outputs.push_back(v.as_single_output_node());
|
||||
}
|
||||
return node_outputs;
|
||||
}
|
||||
} // namespace set_1
|
||||
} // namespace op
|
||||
} // namespace onnx_import
|
||||
} // namespace ngraph
|
46
ngraph/src/ngraph/frontend/onnx_import/op/loop.hpp
Normal file
46
ngraph/src/ngraph/frontend/onnx_import/op/loop.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/node.hpp"
|
||||
#include "ngraph/node.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace onnx_import
|
||||
{
|
||||
namespace op
|
||||
{
|
||||
namespace set_1
|
||||
{
|
||||
/// \brief Creates nGraph node representing ONNX loop operator.
|
||||
///
|
||||
/// \note Details available here:
|
||||
/// https://github.com/onnx/onnx/blob/master/docs/Operators.md#Loop
|
||||
///
|
||||
/// \param[in] node The input ONNX node representing this operation.
|
||||
///
|
||||
/// \return Vector of nodes containting resulting nGraph nodes.
|
||||
///
|
||||
NodeVector loop(const Node& node);
|
||||
} // namespace set_1
|
||||
|
||||
} // namespace op
|
||||
|
||||
} // namespace onnx_import
|
||||
|
||||
} // namespace ngraph
|
@ -196,7 +196,8 @@ namespace ngraph
|
||||
std::end(raw_axes_vec),
|
||||
[](int64_t axis) { return axis >= 0; }),
|
||||
"All axes must be positive when data rank is unknown");
|
||||
axes_vec = std::vector<uint64_t>(std::begin(axes_vec), std::end(axes_vec));
|
||||
axes_vec =
|
||||
std::vector<uint64_t>(std::begin(raw_axes_vec), std::end(raw_axes_vec));
|
||||
}
|
||||
|
||||
const uint64_t slice_indices_length =
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "op/less.hpp"
|
||||
#include "op/log.hpp"
|
||||
#include "op/log_softmax.hpp"
|
||||
#include "op/loop.hpp"
|
||||
#include "op/lp_norm.hpp"
|
||||
#include "op/lp_pool.hpp"
|
||||
#include "op/lrn.hpp"
|
||||
@ -305,6 +306,7 @@ namespace ngraph
|
||||
REGISTER_OPERATOR("Less", 1, less);
|
||||
REGISTER_OPERATOR("Log", 1, log);
|
||||
REGISTER_OPERATOR("LogSoftmax", 1, log_softmax);
|
||||
REGISTER_OPERATOR("Loop", 1, loop);
|
||||
REGISTER_OPERATOR("LpNormalization", 1, lp_norm);
|
||||
REGISTER_OPERATOR("LRN", 1, lrn);
|
||||
REGISTER_OPERATOR("LSTM", 1, lstm);
|
||||
|
@ -0,0 +1,62 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
#include "utils/provenance_tag.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace onnx_import
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
std::string concat_strings(
|
||||
const std::vector<std::reference_wrapper<const std::string>>& strings)
|
||||
{
|
||||
const auto concat_with_comma =
|
||||
[](const std::string& accumulator,
|
||||
std::reference_wrapper<const std::string> next_string) {
|
||||
return accumulator + ", " + next_string.get();
|
||||
};
|
||||
|
||||
return std::accumulate(
|
||||
strings.begin() + 1, strings.end(), strings.begin()->get(), concat_with_comma);
|
||||
}
|
||||
|
||||
std::string build_input_provenance_tag(const std::string& input_name,
|
||||
const PartialShape& shape)
|
||||
{
|
||||
std::stringstream tag_builder;
|
||||
tag_builder << "<ONNX Input (" << input_name << ") Shape:" << shape << ">";
|
||||
return tag_builder.str();
|
||||
}
|
||||
|
||||
std::string build_op_provenance_tag(const Node& onnx_node)
|
||||
{
|
||||
const auto output_names = concat_strings(onnx_node.get_output_names());
|
||||
const auto node_name =
|
||||
onnx_node.get_name().empty() ? "" : onnx_node.get_name() + " ";
|
||||
|
||||
return std::string{"<ONNX " + onnx_node.op_type() + " (" + node_name + "-> " +
|
||||
output_names + ")>"};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace onnx_import
|
||||
} // namespace ngraph
|
@ -0,0 +1,40 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/node.hpp"
|
||||
#include "ngraph/partial_shape.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace onnx_import
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
std::string concat_strings(
|
||||
const std::vector<std::reference_wrapper<const std::string>>& strings);
|
||||
|
||||
std::string build_input_provenance_tag(const std::string& input_name,
|
||||
const PartialShape& shape);
|
||||
|
||||
std::string build_op_provenance_tag(const Node& onnx_node);
|
||||
|
||||
} // namespace detail
|
||||
} // namespace onnx_import
|
||||
} // namespace ngraph
|
@ -40,6 +40,11 @@ bool ngraph::op::v0::PRelu::visit_attributes(AttributeVisitor& visitor)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ngraph::op::v0::PRelu::pre_validate_and_infer_types()
|
||||
{
|
||||
set_output_type(0, get_input_element_type(0), get_input_partial_shape(0));
|
||||
}
|
||||
|
||||
NodeVector op::PRelu::decompose_op() const
|
||||
{
|
||||
auto data = input_value(0);
|
||||
|
@ -47,6 +47,8 @@ namespace ngraph
|
||||
|
||||
virtual std::shared_ptr<Node>
|
||||
clone_with_new_inputs(const OutputVector& new_args) const override;
|
||||
|
||||
void pre_validate_and_infer_types() override;
|
||||
};
|
||||
}
|
||||
using v0::PRelu;
|
||||
|
@ -596,6 +596,18 @@ void op::v0::TensorIterator::validate_and_infer_types()
|
||||
auto axis = concat_output_description->m_axis;
|
||||
|
||||
Shape out_shape{body_value_shape};
|
||||
|
||||
if (body_value_shape.empty())
|
||||
{
|
||||
NODE_VALIDATION_CHECK(
|
||||
this,
|
||||
axis == 0,
|
||||
"Axis must be equal to 0 if concatenated output tensor slices are scalars. "
|
||||
"TensorIterator output index: ",
|
||||
index);
|
||||
out_shape = Shape(1);
|
||||
}
|
||||
|
||||
if (m_num_iterations != -1)
|
||||
{
|
||||
// for simple RNN case where stride is the same as part_size
|
||||
|
@ -66,8 +66,12 @@ namespace ngraph
|
||||
class InputDescription
|
||||
{
|
||||
protected:
|
||||
/// \param input_index Position of the TensorIterator input
|
||||
/// \param body_parameter Body parameter to receive input
|
||||
///
|
||||
/// \brief Constructs a new instance.
|
||||
///
|
||||
/// \param input_index Position of the TensorIterator input
|
||||
/// \param body_parameter_index Body parameter to receive input
|
||||
///
|
||||
InputDescription(uint64_t input_index, uint64_t body_parameter_index);
|
||||
InputDescription() = default;
|
||||
|
||||
@ -83,20 +87,26 @@ namespace ngraph
|
||||
uint64_t m_body_parameter_index{0};
|
||||
};
|
||||
|
||||
/// \brief Describes a body input formed from slices of an input to
|
||||
/// TensorIterator.
|
||||
///
|
||||
/// \brief Describes a body input formed from slices of an input to
|
||||
/// TensorIterator.
|
||||
///
|
||||
class NGRAPH_API SliceInputDescription : public InputDescription
|
||||
{
|
||||
public:
|
||||
static constexpr type_info_t type_info{"SliceInputDescription", 0};
|
||||
const type_info_t& get_type_info() const override { return type_info; }
|
||||
/// \param input_index Position of the TensorIterator input
|
||||
/// \param body_parameter_index Body parameter position to receive input
|
||||
/// \param start First index for slices
|
||||
/// \param stride Step amount for slices
|
||||
/// \param part_size Width of slices
|
||||
/// \param end Last index for slices
|
||||
/// \param axis Axis being sliced
|
||||
///
|
||||
/// \brief Constructs a new instance.
|
||||
///
|
||||
/// \param input_index Position of the TensorIterator input
|
||||
/// \param body_parameter_index Body parameter position to receive input
|
||||
/// \param start First index for slices
|
||||
/// \param stride Step amount for slices
|
||||
/// \param part_size Width of slices
|
||||
/// \param end Last index for slices
|
||||
/// \param axis Axis being sliced
|
||||
///
|
||||
SliceInputDescription(uint64_t input_index,
|
||||
uint64_t body_parameter_index,
|
||||
int64_t start,
|
||||
@ -114,22 +124,26 @@ namespace ngraph
|
||||
int64_t m_axis{0};
|
||||
};
|
||||
|
||||
/// \brief Describes a body input initialized from a TensorIterator input on the
|
||||
/// first
|
||||
/// iteration, and then a body output thereafter.
|
||||
///
|
||||
/// \brief Describes a body input initialized from a TensorIterator input on
|
||||
/// the first iteration, and then a body output thereafter.
|
||||
///
|
||||
class NGRAPH_API MergedInputDescription : public InputDescription
|
||||
{
|
||||
public:
|
||||
static constexpr type_info_t type_info{"MergedInputDescription", 0};
|
||||
const type_info_t& get_type_info() const override { return type_info; }
|
||||
/// \param input_index Position of the TensorIterator input supplying a
|
||||
/// value to
|
||||
/// body_parameter
|
||||
/// for the initial iteration.
|
||||
/// \param body_parameter_index Body parameter position to receive input.
|
||||
/// \param body_value_index Body value to supply body_parameter for
|
||||
///
|
||||
/// \brief Constructs a new instance.
|
||||
///
|
||||
/// \param input_index Position of the TensorIterator input
|
||||
/// supplying a value to body_parameter for
|
||||
/// the initial iteration.
|
||||
/// \param body_parameter_index Body parameter position to receive input.
|
||||
/// \param body_value_index Body value to supply body_parameter for
|
||||
/// successive
|
||||
/// iterations.
|
||||
/// iterations.
|
||||
///
|
||||
MergedInputDescription(uint64_t input_index,
|
||||
uint64_t body_parameter_index,
|
||||
uint64_t body_value_index);
|
||||
@ -158,8 +172,12 @@ namespace ngraph
|
||||
class OutputDescription
|
||||
{
|
||||
protected:
|
||||
/// \param body_value_index A body value that produces the output
|
||||
/// \param output_index The TensorIterator output index
|
||||
///
|
||||
/// \brief Constructs a new instance.
|
||||
///
|
||||
/// \param body_value_index A body value that produces the output
|
||||
/// \param output_index The TensorIterator output index
|
||||
///
|
||||
OutputDescription(uint64_t body_value_index, uint64_t output_index);
|
||||
OutputDescription() = default;
|
||||
|
||||
@ -180,13 +198,17 @@ namespace ngraph
|
||||
public:
|
||||
static constexpr type_info_t type_info{"ConcatOutputDescription", 0};
|
||||
const type_info_t& get_type_info() const override { return type_info; }
|
||||
/// \param body_value_index A body value that produces the output
|
||||
/// \param output_index The TensorIterator output index
|
||||
/// \param start First index for slices
|
||||
/// \param stride Step amount for slices
|
||||
/// \param part_size Width of slices
|
||||
/// \param end Last index for slices
|
||||
/// \param axis Axis being sliced
|
||||
///
|
||||
/// \brief Constructs a new instance.
|
||||
///
|
||||
/// \param body_value_index A body value that produces the output
|
||||
/// \param output_index The TensorIterator output index
|
||||
/// \param start First index for slices
|
||||
/// \param stride Step amount for slices
|
||||
/// \param part_size Width of slices
|
||||
/// \param end Last index for slices
|
||||
/// \param axis Axis being sliced
|
||||
///
|
||||
ConcatOutputDescription(uint64_t body_value_index,
|
||||
uint64_t output_index,
|
||||
int64_t start,
|
||||
@ -211,10 +233,14 @@ namespace ngraph
|
||||
public:
|
||||
static constexpr type_info_t type_info{"BodyOutputDescription", 0};
|
||||
const type_info_t& get_type_info() const override { return type_info; }
|
||||
/// \param body_value_index A body value that produces the output
|
||||
/// \param output_index The TensorIterator output index
|
||||
/// \param iteration which iteration (typically -1, final) will supply the
|
||||
/// value
|
||||
///
|
||||
/// \brief Constructs a new instance.
|
||||
///
|
||||
/// \param body_value_index A body value that produces the output
|
||||
/// \param output_index The TensorIterator output index
|
||||
/// \param iteration which iteration (typically -1, final) will
|
||||
/// supply the value
|
||||
///
|
||||
BodyOutputDescription(uint64_t body_value_index,
|
||||
uint64_t output_index,
|
||||
int64_t iteration);
|
||||
@ -224,15 +250,18 @@ namespace ngraph
|
||||
int64_t m_iteration{0};
|
||||
};
|
||||
|
||||
/// \brief Indicate that a body parameter comes from slices of a value
|
||||
/// \param parameter The parameter to receive the slices
|
||||
/// \param value The value to be sliced. This will be added as an input to
|
||||
/// TensorIterator.
|
||||
/// \param start First index on axis of the slicing
|
||||
/// \param stride Stepping of the slice
|
||||
/// \param part_size Size of the slice on axis
|
||||
/// \param end The last index on axis of the slicing
|
||||
/// \param axis The axis to slice along
|
||||
///
|
||||
/// \brief Indicate that a body parameter comes from slices of a value
|
||||
///
|
||||
/// \param parameter The parameter to receive the slices
|
||||
/// \param value The value to be sliced. This will be added as an input to
|
||||
/// TensorIterator.
|
||||
/// \param start First index on axis of the slicing
|
||||
/// \param stride Stepping of the slice
|
||||
/// \param part_size Size of the slice on axis
|
||||
/// \param end The last index on axis of the slicing
|
||||
/// \param axis The axis to slice along
|
||||
///
|
||||
void set_sliced_input(const std::shared_ptr<Parameter>& parameter,
|
||||
const Output<Node>& value,
|
||||
int64_t start,
|
||||
@ -240,38 +269,52 @@ namespace ngraph
|
||||
int64_t part_size,
|
||||
int64_t end,
|
||||
int64_t axis);
|
||||
/// \brief Indicates that a body parameter has an initial value in the first
|
||||
/// iteration
|
||||
/// and computed value thereafter
|
||||
/// \param initial_value Value for the parameter in first iteration. This will
|
||||
/// be added
|
||||
/// as an input to TensorIterator.
|
||||
/// \param successive_value Value for the parameter in successive iterations.
|
||||
/// The
|
||||
/// value is what is active in the most recent completed iteration.
|
||||
///
|
||||
/// \brief Indicates that a body parameter has an initial value in the first
|
||||
/// iteration and computed value thereafter
|
||||
///
|
||||
/// \param[in] body_parameter The body parameter
|
||||
/// \param initial_value Value for the parameter in first iteration. This
|
||||
/// will be added as an input to TensorIterator.
|
||||
/// \param successive_value Value for the parameter in successive iterations.
|
||||
/// The value is what is active in the most recent
|
||||
/// completed iteration.
|
||||
///
|
||||
void set_merged_input(const std::shared_ptr<Parameter>& body_parameter,
|
||||
const Output<Node>& initial_value,
|
||||
const Output<Node>& successive_value);
|
||||
/// \brief Indicates that a body parameter has an invariant value during
|
||||
/// iteration that
|
||||
/// may depend on values computed outside of the iteration
|
||||
/// \param body_parameter The body parameter
|
||||
/// \param value The value supplied as an input to the block
|
||||
///
|
||||
/// \brief Indicates that a body parameter has an invariant value during
|
||||
/// iteration that may depend on values computed outside of the
|
||||
/// iteration.
|
||||
///
|
||||
/// \param body_parameter The body parameter
|
||||
/// \param value The value supplied as an input to the block
|
||||
///
|
||||
void set_invariant_input(const std::shared_ptr<Parameter>& body_parameter,
|
||||
const Output<Node>& value);
|
||||
/// \brief Gets a value for a particular iteration point
|
||||
/// \param body_value The value
|
||||
/// \param iteration The iteration that supplies the value. Negative values are
|
||||
/// from the
|
||||
/// last iteration.
|
||||
///
|
||||
/// \brief Gets a value for a particular iteration point
|
||||
///
|
||||
/// \param body_value The value
|
||||
/// \param iteration The iteration that supplies the value. Negative values
|
||||
/// are from the last iteration.
|
||||
///
|
||||
/// \return The iterator value.
|
||||
///
|
||||
Output<Node> get_iter_value(const Output<Node>& body_value, int64_t iteration);
|
||||
/// \brief Concatenates slices from all iterations
|
||||
/// \param value The value supplying slice values from each iteration.
|
||||
/// \param start First index on axis of the slicing
|
||||
/// \param stride Stepping of the slice
|
||||
/// \param part_size Size of the slice on axis
|
||||
/// \param end The last index on axis of the slicing
|
||||
/// \param axis The axis to slice along
|
||||
///
|
||||
/// \brief Concatenates slices from all iterations
|
||||
///
|
||||
/// \param value The value supplying slice values from each iteration.
|
||||
/// \param start First index on axis of the slicing
|
||||
/// \param stride Stepping of the slice
|
||||
/// \param part_size Size of the slice on axis
|
||||
/// \param end The last index on axis of the slicing
|
||||
/// \param axis The axis to slice along
|
||||
///
|
||||
/// \return The concatenated slices.
|
||||
///
|
||||
Output<Node> get_concatenated_slices(const Output<Node>& value,
|
||||
int64_t start,
|
||||
int64_t stride,
|
||||
|
@ -405,6 +405,7 @@ set(MULTI_TEST_SRC
|
||||
if (NGRAPH_ONNX_IMPORT_ENABLE)
|
||||
list(APPEND MULTI_TEST_SRC
|
||||
onnx/onnx_import.in.cpp
|
||||
onnx/onnx_import_controlflow.in.cpp
|
||||
onnx/onnx_import_const_folding.in.cpp
|
||||
onnx/onnx_import_convpool.in.cpp
|
||||
onnx/onnx_import_dyn_shapes.in.cpp
|
||||
|
185
ngraph/test/models/onnx/loop_2d_add.prototxt
Normal file
185
ngraph/test/models/onnx/loop_2d_add.prototxt
Normal file
@ -0,0 +1,185 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: ""
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
node {
|
||||
input: "a_in"
|
||||
input: "b"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Identity"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
name: "simple add"
|
||||
initializer {
|
||||
dims: 1
|
||||
dims: 2
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
name: "b"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
191
ngraph/test/models/onnx/loop_2d_add_const_cond.prototxt
Normal file
191
ngraph/test/models/onnx/loop_2d_add_const_cond.prototxt
Normal file
@ -0,0 +1,191 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: "cond_in"
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
node {
|
||||
input: "a_in"
|
||||
input: "b"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Identity"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
name: "simple add"
|
||||
initializer {
|
||||
dims: 1
|
||||
dims: 2
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
name: "b"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 9
|
||||
int32_data: 00000001
|
||||
name: "cond_in"
|
||||
}
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: ""
|
||||
input: "from_body_scope"
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
node {
|
||||
input: "a_in"
|
||||
input: "b"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Identity"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
name: "simple add"
|
||||
initializer {
|
||||
dims: 1
|
||||
dims: 2
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
name: "b"
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
dims: 2
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
name: "from_body_scope"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: ""
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
name: "simple add"
|
||||
node {
|
||||
input: "a_in"
|
||||
input: "b"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Identity"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
dims: 2
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
name: "b"
|
||||
}
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: ""
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
name: "simple add"
|
||||
node {
|
||||
input: "a_in"
|
||||
input: "a_init"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Identity"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
185
ngraph/test/models/onnx/loop_2d_add_no_identity_cond.prototxt
Normal file
185
ngraph/test/models/onnx/loop_2d_add_no_identity_cond.prototxt
Normal file
@ -0,0 +1,185 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: ""
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
node {
|
||||
input: "a_in"
|
||||
input: "b"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Not"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
name: "simple add"
|
||||
initializer {
|
||||
dims: 1
|
||||
dims: 2
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
name: "b"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
@ -0,0 +1,207 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "a_init"
|
||||
input: "scale"
|
||||
name: "mul_node"
|
||||
op_type: "Mul"
|
||||
output: "b"
|
||||
}
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: ""
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
name: "simple add"
|
||||
node {
|
||||
input: "b"
|
||||
input: "a_init"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Identity"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 1
|
||||
float_data: 2
|
||||
name: "scale"
|
||||
}
|
||||
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "b"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
194
ngraph/test/models/onnx/loop_2d_add_the_same_name.prototxt
Normal file
194
ngraph/test/models/onnx/loop_2d_add_the_same_name.prototxt
Normal file
@ -0,0 +1,194 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: ""
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
node {
|
||||
input: "a_in"
|
||||
input: "b"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Identity"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
name: "simple add"
|
||||
initializer {
|
||||
dims: 1
|
||||
dims: 2
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
name: "b"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
initializer {
|
||||
dims: 1
|
||||
dims: 3
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
float_data: 1
|
||||
name: "b"
|
||||
}
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
145
ngraph/test/models/onnx/loop_scalars_add.prototxt
Normal file
145
ngraph/test/models/onnx/loop_scalars_add.prototxt
Normal file
@ -0,0 +1,145 @@
|
||||
ir_version: 6
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
name: "basic loop"
|
||||
node {
|
||||
input: "trip_count"
|
||||
input: ""
|
||||
input: "a_init"
|
||||
output: "a_final"
|
||||
output: "a_values"
|
||||
op_type: "Loop"
|
||||
attribute {
|
||||
name: "body"
|
||||
g {
|
||||
node {
|
||||
input: "a_in"
|
||||
input: "b"
|
||||
output: "current_a"
|
||||
name: "loop_body_add"
|
||||
op_type: "Add"
|
||||
}
|
||||
node {
|
||||
input: "cond"
|
||||
output: "cond_out"
|
||||
name: "cond_identity"
|
||||
op_type: "Identity"
|
||||
}
|
||||
node {
|
||||
input: "current_a"
|
||||
output: "a_out"
|
||||
name: "output_accumulator"
|
||||
op_type: "Identity"
|
||||
}
|
||||
name: "simple add"
|
||||
initializer {
|
||||
data_type: 1
|
||||
float_data: 1
|
||||
name: "b"
|
||||
}
|
||||
input {
|
||||
name: "i"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 7
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "cond"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
name: "a_in"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "cond_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 9
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "current_a"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_out"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: GRAPH
|
||||
}
|
||||
}
|
||||
initializer {
|
||||
data_type: 7
|
||||
int64_data: 3
|
||||
name: "trip_count"
|
||||
}
|
||||
input {
|
||||
name: "a_init"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_final"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "a_values"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 11
|
||||
}
|
238
ngraph/test/onnx/onnx_import_controlflow.in.cpp
Normal file
238
ngraph/test/onnx/onnx_import_controlflow.in.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
//*****************************************************************************
|
||||
// Copyright 2017-2020 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//*****************************************************************************
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/file_util.hpp"
|
||||
#include "ngraph/frontend/onnx_import/default_opset.hpp"
|
||||
#include "ngraph/frontend/onnx_import/onnx.hpp"
|
||||
#include "ngraph/type/element_type.hpp"
|
||||
#include "util/test_case.hpp"
|
||||
#include "util/test_control.hpp"
|
||||
#include "util/test_tools.hpp"
|
||||
#include "util/type_prop.hpp"
|
||||
|
||||
using namespace ngraph;
|
||||
using namespace ngraph::onnx_import;
|
||||
using namespace ngraph::test;
|
||||
|
||||
static std::string s_manifest = "${MANIFEST}";
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_check_model)
|
||||
{
|
||||
// The model contains a loop which has statically set iterations count equal 3.
|
||||
// In the loop body there is just simple add operation.
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add.prototxt"));
|
||||
|
||||
const auto& parameters = function->get_parameters();
|
||||
EXPECT_EQ(parameters.size(), 1);
|
||||
EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32);
|
||||
EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static());
|
||||
EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2}));
|
||||
|
||||
const auto& results = function->get_results();
|
||||
EXPECT_EQ(results.size(), 2);
|
||||
EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(0).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2}));
|
||||
EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(1).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2}));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_scalars_check_model)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/loop_scalars_add.prototxt"));
|
||||
|
||||
const auto& parameters = function->get_parameters();
|
||||
EXPECT_EQ(parameters.size(), 1);
|
||||
EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32);
|
||||
EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static());
|
||||
EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{}));
|
||||
|
||||
const auto& results = function->get_results();
|
||||
EXPECT_EQ(results.size(), 2);
|
||||
EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(0).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(0), (Shape{}));
|
||||
EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(1).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(1), (Shape{3}));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_initializer_from_parent_scope)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(file_util::path_join(
|
||||
SERIALIZED_ZOO, "onnx/loop_2d_add_initializer_from_parent_scope.prototxt"));
|
||||
|
||||
const auto& parameters = function->get_parameters();
|
||||
EXPECT_EQ(parameters.size(), 1);
|
||||
EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32);
|
||||
EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static());
|
||||
EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2}));
|
||||
|
||||
const auto& results = function->get_results();
|
||||
EXPECT_EQ(results.size(), 2);
|
||||
EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(0).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2}));
|
||||
EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(1).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2}));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_input_from_parent_scope)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_input_from_parent_scope.prototxt"));
|
||||
|
||||
const auto& parameters = function->get_parameters();
|
||||
EXPECT_EQ(parameters.size(), 1);
|
||||
EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32);
|
||||
EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static());
|
||||
EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2}));
|
||||
|
||||
const auto& results = function->get_results();
|
||||
EXPECT_EQ(results.size(), 2);
|
||||
EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(0).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2}));
|
||||
EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(1).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2}));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_node_from_parent_scope)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_node_from_parent_scope.prototxt"));
|
||||
|
||||
const auto& parameters = function->get_parameters();
|
||||
EXPECT_EQ(parameters.size(), 1);
|
||||
EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32);
|
||||
EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static());
|
||||
EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2}));
|
||||
|
||||
const auto& results = function->get_results();
|
||||
EXPECT_EQ(results.size(), 3);
|
||||
EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(0).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2}));
|
||||
EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(1).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2}));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_value_access_to_body_scope_exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(file_util::path_join(
|
||||
SERIALIZED_ZOO, "onnx/loop_2d_add_incorrect_access_body_scope.prototxt"));
|
||||
FAIL() << "Incorrect access to body scope not detected";
|
||||
}
|
||||
catch (const ngraph_error& e)
|
||||
{
|
||||
// patent graph should have no access to subgraph (body Loop) scope
|
||||
EXPECT_HAS_SUBSTRING(e.what(),
|
||||
std::string("from_body_scope node not found in graph cache"));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Deduced type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_value_the_same_node_from_parent_and_subgraph)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_the_same_name.prototxt"));
|
||||
|
||||
const auto& parameters = function->get_parameters();
|
||||
EXPECT_EQ(parameters.size(), 1);
|
||||
EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32);
|
||||
EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static());
|
||||
EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2}));
|
||||
|
||||
const auto& results = function->get_results();
|
||||
EXPECT_EQ(results.size(), 2);
|
||||
EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(0).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2}));
|
||||
EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(1).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2}));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_exception_if_no_identity_cond)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_no_identity_cond.prototxt"));
|
||||
FAIL() << "Not supported termination loop condition exception not thrown";
|
||||
}
|
||||
catch (const ngraph_error& e)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(
|
||||
e.what(),
|
||||
std::string(
|
||||
"Given termination loop condition input is not supported by Loop operator"));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Deduced type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_const_cond)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_const_cond.prototxt"));
|
||||
|
||||
const auto& parameters = function->get_parameters();
|
||||
EXPECT_EQ(parameters.size(), 1);
|
||||
EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32);
|
||||
EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static());
|
||||
EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2}));
|
||||
|
||||
const auto& results = function->get_results();
|
||||
EXPECT_EQ(results.size(), 2);
|
||||
EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(0).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2}));
|
||||
EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32);
|
||||
EXPECT_TRUE(function->get_output_partial_shape(1).is_static());
|
||||
EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2}));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_execution)
|
||||
{
|
||||
// The model contains a loop which has statically set iterations count equal 3.
|
||||
// In the loop body there is just simple add operation.
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add.prototxt"));
|
||||
|
||||
auto test_case = NgraphTestCase(function, "${BACKEND_NAME}");
|
||||
|
||||
// a_init
|
||||
test_case.add_input<float>({0.f, 0.f});
|
||||
|
||||
test_case.add_expected_output<float>(Shape{1, 2}, {3.f, 3.f});
|
||||
test_case.add_expected_output<float>(Shape{3, 2}, {1.f, 1.f, 2.f, 2.f, 3.f, 3.f});
|
||||
test_case.run();
|
||||
}
|
@ -1695,3 +1695,6 @@ IE_GPU.matmul_2x2_2x2
|
||||
IE_GPU.matmul_2x3_3x3
|
||||
IE_GPU.matmul_3x2_3x3_transpose
|
||||
IE_GPU.matmul_3x2_2x3_transpose
|
||||
|
||||
# ONNX Loop
|
||||
onnx_controlflow_loop_2d_add_execution
|
||||
|
@ -10,6 +10,9 @@ INTERPRETER.onnx_top_k_opset_10
|
||||
reduce_sum_large_1d_to_scalar
|
||||
reduce_sum_keep_large_1d_to_scalar
|
||||
|
||||
# ONNX Loop
|
||||
onnx_controlflow_loop_2d_add_execution
|
||||
|
||||
# Disabled tests for disabled reference implementations
|
||||
INTERPRETER.onnx_model_qlinear_matmul_3d
|
||||
INTERPRETER.onnx_dyn_shapes_expand_uint16_dyn_shape
|
||||
|
Loading…
Reference in New Issue
Block a user