attribute_visitor.hpp
1 //*****************************************************************************
2 // Copyright 2017-2021 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
16 
17 #pragma once
18 
19 #include <string>
20 #include <unordered_map>
21 #include <utility>
22 
23 #include "ngraph/partial_shape.hpp"
24 #include "ngraph/type.hpp"
25 #include "ngraph/type/element_type.hpp"
26 
27 namespace ngraph
28 {
29  template <typename T>
30  class ValueAccessor;
31  class VisitorAdapter;
32  class Node;
33  class Function;
34 
35  /// \brief Visits the attributes of a node, primarily for serialization-like tasks.
36  ///
37  /// Attributes are the node parameters that are always compile-time constants.
38  /// Values computed from the graph topology and attributes during compilation are not
39  /// attributes.
40  ///
41  /// Attributes have a wide variety of types, but serialization formats are more restricted.
42  /// We asume serialation easily supports scalar types of bool 64-bit signed, string, and double,
43  /// and has specialized ways to support numeric arrays and raw data+size. The visitor and
44  /// adapter convert between the limited serialization types and the unlimited attribute types.
45  ///
46  /// A visitor is passed to an op's visit_attributes method. The visit_attributes method calls
47  /// the template method visitor.on_attribute<AT>(const std::string& name, AT& value) on each
48  /// attribute. The visitor can read or write the attribute's value. The on_attribute
49  /// method creates an AttributeAdapter<AT> for the value and passes it to one of the visitors
50  /// on_adapter methods. The on_adapter methods expect a reference to a ValueAccessor<VAT> or a
51  /// VisitorAdapter. A ValueAccessor<VAT> has get/set methods that can be used to read/write the
52  /// attribute value as type VAT. These methods are triggered by deriving AttributeAdapter<AT>
53  /// from ValueAccessor<VAT>. For more complex cases, such as structs, the on_adapter method for
54  /// VisitorAdapter passes the name and visitor to the adapter, so that the adapter can perform
55  /// additional work such as visiting struct members or sequence values.
56  ///
57  /// When a node visits an attribute with structure, the node's on_attribute passes a name for
58  /// the entire attribute, but the struct will have its own methods to be visited. Similarly, a
59  /// vector will have a sequence of members to be visited. The adapter may use the visitor
60  /// methods start_struct/finish_struct and start_vector/next_vector/finish_vector to inidicate
61  /// nexted members.
62  ///
63  /// The visitor method get_name_with_context creates a generic nested version of the name.
64  /// Visitors can override according to their serialization requirements.
65  ///
66  /// Attributes that are shared_ptr<Node> are special. They must have been already been
67  /// registered with the visitor using register_node, which needs a shared pointer to a node and
68  /// a string ID. The ID string will be used to serialize the node or find the node during
69  /// deserialization.
70  class NGRAPH_API AttributeVisitor
71  {
72  public:
73  virtual ~AttributeVisitor() {}
74  // Must implement these methods
75  /// \brief handles all specialized on_adapter methods implemented by the visitor.
76  ///
77  /// The adapter implements get_type_info(), which can be used to determine the adapter
78  /// directly
79  /// or via is_type and as_type on any platform
80  virtual void on_adapter(const std::string& name, ValueAccessor<void>& adapter) = 0;
81  // The remaining adapter methods fall back on the void adapter if not implemented
82  virtual void on_adapter(const std::string& name, ValueAccessor<void*>& adapter);
83  virtual void on_adapter(const std::string& name, ValueAccessor<std::string>& adapter);
84  virtual void on_adapter(const std::string& name, ValueAccessor<bool>& adapter);
85  virtual void on_adapter(const std::string& name, ValueAccessor<int8_t>& adapter);
86  virtual void on_adapter(const std::string& name, ValueAccessor<int16_t>& adapter);
87  virtual void on_adapter(const std::string& name, ValueAccessor<int32_t>& adapter);
88  virtual void on_adapter(const std::string& name, ValueAccessor<int64_t>& adapter);
89  virtual void on_adapter(const std::string& name, ValueAccessor<uint8_t>& adapter);
90  virtual void on_adapter(const std::string& name, ValueAccessor<uint16_t>& adapter);
91  virtual void on_adapter(const std::string& name, ValueAccessor<uint32_t>& adapter);
92  virtual void on_adapter(const std::string& name, ValueAccessor<uint64_t>& adapter);
93  virtual void on_adapter(const std::string& name, ValueAccessor<float>& adapter);
94  virtual void on_adapter(const std::string& name, ValueAccessor<double>& adapter);
95  virtual void on_adapter(const std::string& name,
96  ValueAccessor<std::vector<int8_t>>& adapter);
97  virtual void on_adapter(const std::string& name,
98  ValueAccessor<std::vector<int16_t>>& adapter);
99  virtual void on_adapter(const std::string& name,
100  ValueAccessor<std::vector<int32_t>>& adapter);
101  virtual void on_adapter(const std::string& name,
102  ValueAccessor<std::vector<int64_t>>& adapter);
103  virtual void on_adapter(const std::string& name,
104  ValueAccessor<std::vector<uint8_t>>& adapter);
105  virtual void on_adapter(const std::string& name,
106  ValueAccessor<std::vector<uint16_t>>& adapter);
107  virtual void on_adapter(const std::string& name,
108  ValueAccessor<std::vector<uint32_t>>& adapter);
109  virtual void on_adapter(const std::string& name,
110  ValueAccessor<std::vector<uint64_t>>& adapter);
111  virtual void on_adapter(const std::string& name,
112  ValueAccessor<std::vector<float>>& adapter);
113  virtual void on_adapter(const std::string& name,
114  ValueAccessor<std::vector<double>>& adapter);
115  virtual void on_adapter(const std::string& name,
116  ValueAccessor<std::vector<std::string>>& adapter);
117  /// \brief Hook for adapters that need visitor access
118  virtual void on_adapter(const std::string& name, VisitorAdapter& adapter);
119 
120  /// \brief Provides API to handle nGraph Function attribute type, accessed as ValueAccessor
121  /// \param name attribute name
122  /// \param adapter reference to a Function ValueAccessor<VAT>
123  virtual void on_adapter(const std::string& name,
124  ValueAccessor<std::shared_ptr<Function>>& adapter);
125 
126  /// The generic visitor. There must be a definition of AttributeAdapter<T> that can convert
127  /// to a ValueAccessor<U> for one of the on_adpater methods.
128  template <typename AT>
129  void on_attribute(const std::string& name, AT& value)
130  {
131  AttributeAdapter<AT> adapter(value);
132  start_structure(name);
133  on_adapter(get_name_with_context(), adapter);
134  finish_structure();
135  }
136  /// \returns The nested context of visits
137  const std::vector<std::string>& get_context() const { return m_context; }
138  /// \returns context prepended to names
139  virtual std::string get_name_with_context();
140  /// \brief Start visiting a nested structure
141  virtual void start_structure(const std::string& name);
142  /// \brief Finish visiting a nested structure
143  virtual std::string finish_structure();
144  using node_id_t = std::string;
145  static const node_id_t invalid_node_id;
146  /// \brief Associate a node with an id.
147  ///
148  /// No node may be used as an attribute unless it has already been registered with an ID.
149  /// References to nodes are visited with a ValueAccessor of their ID.
150  virtual void register_node(const std::shared_ptr<Node>& node,
151  node_id_t id = invalid_node_id);
152  /// Returns the node with the given id, or nullptr if there is no registered node
153  virtual std::shared_ptr<Node> get_registered_node(node_id_t id);
154  /// Returns the id for the node, or -1 if the node is not registered
155  virtual node_id_t get_registered_node_id(const std::shared_ptr<Node>& node);
156 
157  protected:
158  std::vector<std::string> m_context;
159  std::unordered_map<std::shared_ptr<Node>, node_id_t> m_node_id_map;
160  std::unordered_map<node_id_t, std::shared_ptr<Node>> m_id_node_map;
161  };
162 }
An AttributeAdapter "captures" an attribute as an AT& and makes it available as a ValueAccessor<VAT>.
Definition: attribute_adapter.hpp:171
Visits the attributes of a node, primarily for serialization-like tasks.
Definition: attribute_visitor.hpp:71
virtual void on_adapter(const std::string &name, VisitorAdapter &adapter)
Hook for adapters that need visitor access.
virtual void start_structure(const std::string &name)
Start visiting a nested structure.
void on_attribute(const std::string &name, AT &value)
Definition: attribute_visitor.hpp:129
virtual void on_adapter(const std::string &name, ValueAccessor< std::shared_ptr< Function >> &adapter)
Provides API to handle nGraph Function attribute type, accessed as ValueAccessor.
virtual std::string get_name_with_context()
const std::vector< std::string > & get_context() const
Definition: attribute_visitor.hpp:137
virtual std::shared_ptr< Node > get_registered_node(node_id_t id)
Returns the node with the given id, or nullptr if there is no registered node.
virtual void on_adapter(const std::string &name, ValueAccessor< void > &adapter)=0
handles all specialized on_adapter methods implemented by the visitor.
virtual std::string finish_structure()
Finish visiting a nested structure.
virtual void register_node(const std::shared_ptr< Node > &node, node_id_t id=invalid_node_id)
Associate a node with an id.
virtual node_id_t get_registered_node_id(const std::shared_ptr< Node > &node)
Returns the id for the node, or -1 if the node is not registered.
ValueAccessor<void> provides an accessor for values that do not have get/set methonds via AttributeVi...
Definition: attribute_adapter.hpp:42
Definition: attribute_adapter.hpp:71
Adapters will see visitor.
Definition: attribute_adapter.hpp:194
The Intel nGraph C++ API.
Definition: attribute_adapter.hpp:28