Caffe2 - C++ API
A deep learning, cross platform ML framework
interned_strings.h
1 #pragma once
2 #include <vector>
3 #include <cstdint>
4 #include <string>
5 #include <unordered_map>
6 #include <algorithm>
7 
8 #include <ATen/core/aten_interned_strings.h>
9 #include <c10/macros/Macros.h>
10 
11 namespace c10 {
12 
13 #ifndef C10_MOBILE
14 #define FORALL_NS_SYMBOLS(_) \
15  _(namespaces, prim) \
16  _(namespaces, aten) \
17  _(namespaces, onnx) \
18  _(namespaces, attr) \
19  _(namespaces, scope) \
20  _(namespaces, user) \
21  _(namespaces, namespaces) \
22  _(prim, Assign) \
23  _(prim, BroadcastingChunk) \
24  _(prim, BroadcastSizes) \
25  _(prim, Constant) \
26  _(prim, ChunkSizes) \
27  _(prim, Drop) \
28  _(prim, Eval) \
29  _(prim, Expand) /* onnx */ \
30  _(prim, FusionGroup) \
31  _(prim, DifferentiableGraph) \
32  _(prim, If) \
33  _(prim, Jump) /* debug */ \
34  _(prim, JumpNZ) /* debug */ \
35  _(prim, JumpZ) /* debug */ \
36  _(prim, Load) \
37  _(prim, Loop) \
38  _(prim, Param) \
39  _(prim, PackPadded) /* onnx */ \
40  _(prim, PadPacked) /* onnx */ \
41  _(prim, Placeholder) /* debug */ \
42  _(prim, Print) \
43  _(prim, PythonOp) \
44  _(prim, IgnoredPythonOp) \
45  _(prim, Reverse) \
46  _(prim, Return) \
47  _(prim, Store) \
48  _(prim, AutogradZero) \
49  _(prim, AutogradAnyNonZero) \
50  _(prim, Starred) \
51  _(prim, TupleConstruct) \
52  _(prim, TupleUnpack) \
53  _(prim, TupleIndex) \
54  _(prim, TupleSlice) \
55  _(prim, ListConstruct) \
56  _(prim, ListUnpack) \
57  _(prim, DictConstruct) \
58  _(prim, DictIndex) \
59  _(prim, NumToTensor) \
60  _(prim, ImplicitTensorToNum) \
61  _(prim, Bool) \
62  _(prim, Int) \
63  _(prim, Float) \
64  _(prim, device) \
65  _(prim, dtype) \
66  _(prim, shape) \
67  _(prim, requires_grad) \
68  _(prim, AutogradAdd) \
69  _(prim, GradOf) \
70  _(prim, FusedConcat) \
71  _(prim, ConstantChunk) \
72  _(prim, MMTreeReduce) \
73  _(prim, MMBatchSide) \
74  _(prim, min) \
75  _(prim, max) \
76  _(prim, rangelist) \
77  _(aten, _grad_sum_to_size) \
78  _(aten, _ncf_unsqueeze) \
79  _(aten, warn) \
80  _(aten, floordiv) \
81  _(aten, __round_to_zero_floordiv)\
82  _(aten, _unwrap_optional) \
83  _(prim, fork) \
84  _(prim, RaiseException) \
85  _(prim, Function) \
86  _(prim, CreateObject) \
87  _(prim, SetAttr) \
88  _(prim, GetAttr) \
89  _(aten, append) \
90  _(aten, item) \
91  _(aten, format) \
92  _(aten, __not__) \
93  _(aten, __is__) \
94  _(aten, __isnot__) \
95  _(aten, copy_) \
96  _(aten, _set_item) \
97  _(aten, index_put_) \
98  _(aten, device) \
99  _(aten, len) \
100  _(aten, list) \
101  _(aten, wait) \
102  _(prim, unchecked_unwrap_optional)\
103  FORALL_ATEN_BASE_SYMBOLS(_) \
104  _(onnx, Add) \
105  _(onnx, Concat) \
106  _(onnx, Constant) \
107  _(onnx, ConstantFill) \
108  _(onnx, Div) \
109  _(onnx, GRU) \
110  _(onnx, Gather) \
111  _(onnx, Gemm) \
112  _(onnx, LSTM) \
113  _(onnx, Mul) \
114  _(onnx, Pow) \
115  _(onnx, RNN) \
116  _(onnx, Shape) \
117  _(onnx, Size) \
118  _(onnx, Slice) \
119  _(onnx, Squeeze) \
120  _(onnx, Sub) \
121  _(onnx, Transpose) \
122  _(onnx, Unsqueeze) \
123  _(onnx, Loop) \
124  _(onnx, If) \
125  _(onnx, Reshape) \
126  _(onnx, Equal) \
127  _(onnx, Greater) \
128  _(onnx, Less) \
129  _(onnx, Not) \
130  _(onnx, ATen) \
131  _(onnx, Split) \
132  _(onnx, ConstantOfShape) \
133  FORALL_ATTR_BASE_SYMBOLS(_) \
134  _(attr, Subgraph) \
135  _(attr, ReverseSubgraph) \
136  _(attr, f_real_outputs) \
137  _(attr, df_input_vjps) \
138  _(attr, df_input_captured_inputs) \
139  _(attr, df_input_captured_outputs) \
140  _(attr, df_output_vjps) \
141  _(attr, axes) \
142  _(attr, axis) \
143  _(attr, broadcast) \
144  _(attr, direction) \
145  _(attr, ends) \
146  _(attr, inplace) \
147  _(attr, input_as_shape) \
148  _(attr, is_zero) \
149  _(attr, perm) \
150  _(attr, sizes) \
151  _(attr, starts) \
152  _(attr, transA) \
153  _(attr, transB) \
154  _(attr, name) \
155  _(attr, a) \
156  _(attr, b) \
157  _(attr, beg) \
158  _(attr, idx) \
159  _(attr, split) \
160  _(attr, slot)
161 #else
162 #define FORALL_NS_SYMBOLS(_) \
163  _(namespaces, prim) \
164  _(namespaces, aten) \
165  _(namespaces, onnx) \
166  _(namespaces, attr) \
167  _(namespaces, scope) \
168  _(namespaces, user) \
169  _(namespaces, namespaces)
170 #endif
171 
172 // 'prim' symbols are synthetic operators that occur only in the IR
173 // and don't have corresponding implementations in ATen.
174 
175 // 'onnx' symbols correspond to ONNX operators. Their semantics
176 // are defined in https://github.com/onnx/onnx/blob/master/docs/Operators.md
177 // The particular version we are targeting is specified by '_onnx_opset_version'
178 // in torch.onnx.symbolic
179 //
180 // In general, most ONNX operators won't get an entry here, because they
181 // are handled from the Python end. However, you may occasionally need
182 // to intern an ONNX symbol here so that you can conveniently write an
183 // optimization on ONNX operations.
184 
185 // 'attr' symbols are attribute keys. They are shared between both ONNX and ATen
186 // operators (you disambiguate their meaning by looking at the operator itself).
187 // In general, you only need to define attribute keys that are used by
188 // onnx or prim; ATen attributes are automatically generated in FORALL_ATTR_BASE_SYMBOLS.
189 
190 // Note [Symbol allocation]
191 // ~~~~~~~~~~~~~~~~~~~~~~~~
192 //
193 // 1. Symbol namespace is split up into namespaces.
194 //
195 // 2. The intended access pattern for built-in symbols is onnx::MatMul
196 // in the c10 namespace (this is a Symbol).
197 //
198 
199 // Built-in constant definition strategy:
200 // - Enum is the most convenient way to generate a contiguous sequence
201 // of numbers for an identifier.
202 // - However, an enum gives you a fresh type. We want onnx::MatMul to
203 // be type Symbol, not some random enum type!
204 // - Therefore, after using enums to generate the sequence of integers,
205 // we then declare constexpr Symbols to get everything the actual Symbol
206 // type we want. Symbols must be constexpr to be valid to be "case"ed on.
207 
208 using unique_t = uint32_t;
209 
210 const std::string& domain_prefix();
211 
212 // A Symbol is like an interned string, but with a little extra
213 // structure; it is namespaced via SymbolNamespace and the resulting
214 // intern pointers support efficient namespace testing.
215 struct CAFFE2_API Symbol {
216  explicit constexpr Symbol() : value(0) {};
217  explicit constexpr Symbol(unique_t uniq)
218  : value(uniq) {}
219 
220  // Get a Symbol for a qualified string like "attr::bar"
221  static Symbol fromQualString(const std::string & s);
222 
223  // Get a Symbol from a domain and an unqualified string like "org.pytorch.attr" and "bar"
224  static Symbol fromDomainAndUnqualString(const std::string & d, const std::string & s);
225 
226  // Constructors for our various namespaced strings. This will construct
227  // the appropriate namespaced string, e.g., "attr::foo" for the
228  // argument "foo", and then attempt to intern it. DO NOT USE THIS
229  // with a string literal; attr::foo should be available in that case
230  // (and if it's not, you should add it to the built-ins list above.)
231  static Symbol attr(const std::string & s);
232  static Symbol aten(const std::string & s);
233  static Symbol onnx(const std::string & s);
234  static Symbol prim(const std::string & s);
235  static Symbol user(const std::string & s);
236  // TODO: eliminate me
237  static Symbol scope(const std::string & s);
238 
239  bool is_attr() const;
240  bool is_aten() const;
241  bool is_prim() const;
242  bool is_onnx() const;
243  bool is_user() const;
244 
245  // So we can switch on this
246  constexpr operator unique_t() const {
247  return value;
248  }
249 
250  Symbol ns() const;
251 
252  // Give a string corresponding to the unqualified version of this name, e.g.,
253  // "mm". Use this in a context where the intended namespace of the string is
254  // obvious; this is a *lossy* conversion.
255  const char * toUnqualString() const;
256 
257  // Give a string corresponding to the qualified version of this name,
258  // e.g., "aten::mm". This string format is made available to Python bindings
259  // (so we know how to parse it.)
260  const char * toQualString() const;
261 
262  // This describes a symbol in a case where humans read it. At the moment it's
263  // the same as toQualString. This has to be a const char* returned because
264  // a lot of printf style macros use it.
265  const char * toDisplayString() const;
266 
267  // Give a string corresponding to the domain name for the symbol,
268  // e.g., "org.pytorch.aten".
269  std::string domainString() const;
270 
271 private:
272  explicit Symbol(Symbol ns, const std::string & s);
273  unique_t value;
274 };
275 
276 static inline bool operator==(Symbol lhs, Symbol rhs) {
277  return static_cast<unique_t>(lhs) == static_cast<unique_t>(rhs);
278 }
279 
280 enum class _keys : unique_t {
281  #define DEFINE_KEY(ns, s) ns##_##s,
282  FORALL_NS_SYMBOLS(DEFINE_KEY)
283  #undef DEFINE_KEY
284  num_symbols
285 };
286 
287 #define DEFINE_SYMBOL(s) \
288  constexpr Symbol s(static_cast<unique_t>(_keys::s));
289 
290 #undef DEFINE_SYMBOL
291 
292 #define DEFINE_SYMBOL(ns, s) \
293  namespace ns { constexpr Symbol s(static_cast<unique_t>(_keys::ns##_##s)); }
294 FORALL_NS_SYMBOLS(DEFINE_SYMBOL)
295 #undef DEFINE_SYMBOL
296 
297 inline Symbol Symbol::attr(const std::string & s) { return Symbol::fromQualString("attr::" + s); }
298 inline Symbol Symbol::aten(const std::string & s) { return Symbol::fromQualString("aten::" + s); }
299 inline Symbol Symbol::onnx(const std::string & s) { return Symbol::fromQualString("onnx::" + s); }
300 inline Symbol Symbol::prim(const std::string & s) { return Symbol::fromQualString("prim::" + s); }
301 inline Symbol Symbol::scope(const std::string & s) { return Symbol::fromQualString("scope::" + s); }
302 inline Symbol Symbol::user(const std::string & s) { return Symbol::fromQualString("user::" + s); }
303 inline bool Symbol::is_attr() const { return ns() == namespaces::attr; }
304 inline bool Symbol::is_aten() const { return ns() == namespaces::aten; }
305 inline bool Symbol::is_prim() const { return ns() == namespaces::prim; }
306 inline bool Symbol::is_onnx() const { return ns() == namespaces::onnx; }
307 inline bool Symbol::is_user() const { return ns() == namespaces::user; }
308 
309 } // namespace c10
310 
311 // make symbol behave like an integer in hash tables
312 namespace std {
313 template <>
314 struct hash<c10::Symbol> {
315  size_t operator()(c10::Symbol s) const {
316  return std::hash<uint32_t>()(static_cast<uint32_t>(s));
317  }
318 };
319 }
To register your own kernel for an operator, do in one (!) cpp file: C10_REGISTER_KERNEL(OperatorHand...
Definition: alias_info.h:7