ONE - On-device Neural Engine
Loading...
Searching...
No Matches
GraphBuilder.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
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#ifndef __GRAPH_BUILDER_H__
18#define __GRAPH_BUILDER_H__
19
20// loco-internal headers
21#include "loco/IR/Graph.h"
22
23// C++ standard headers
24#include <memory>
25#include <stack>
26
27//
28// This file includes a stack-based loco graph builder
29//
30// HOW TO USE
31//
32// loco::Graph *g = ...
33// auto builder = make_graph_builder(g);
34//
35// builder->push<YourAwesomeLayer>(...);
36//
37
38class GraphBuilder final
39{
40public:
41 class Stack final
42 {
43 public:
44 Stack() = default;
45
46 public:
47 loco::Node *top(void) const { return _content.top(); }
48
49 public:
51 {
52 auto ret = top();
53 _content.pop();
54 return ret;
55 }
56
57 public:
58 void push(loco::Node *node) { _content.push(node); }
59
60 private:
61 std::stack<loco::Node *> _content;
62 };
63
64 class Context final
65 {
66 public:
68 {
69 // DO NOTHING
70 }
71
72 public:
73 loco::Graph *graph(void) { return _graph; }
74 Stack *stack(void) { return &_stack; }
75
76 private:
77 loco::Graph *_graph = nullptr;
78 Stack _stack;
79 };
80
81public:
82 GraphBuilder(loco::Graph *graph) : _context{graph}
83 {
84 // DO NOTHING
85 }
86
87public:
88 // "Layer" is in theory a subgraph builder.
89 template <typename Layer, typename... Args>
90 auto push(Args &&...args)
91 -> decltype(static_cast<Layer *>(nullptr)->operator()(static_cast<Context *>(nullptr)))
92 {
93 Layer layer{std::forward<Args>(args)...};
94 return layer(ctx());
95 }
96
97public:
98 loco::Node *pop(void) { return ctx()->stack()->pop(); }
99
100private:
101 Context *ctx(void) { return &_context; }
102
103private:
104 Context _context;
105};
106
107static inline std::unique_ptr<GraphBuilder> make_graph_builder(loco::Graph *g)
108{
109 return std::make_unique<GraphBuilder>(g);
110}
111
112// "InputLayer" creates both GraphInput and Pull node at once
113struct InputLayer final
114{
115 class Return
116 {
117 public:
118 Return(loco::GraphInput *input, loco::Pull *node) : _input{input}, _node{node}
119 {
120 // DO NOTHING
121 }
122
123 public:
124 loco::Pull *node(void) { return _node; }
125
126 public:
127 Return *name(const std::string &value)
128 {
129 _input->name(value);
130 return this;
131 }
132
133 public:
134 Return *shape(std::initializer_list<uint32_t> dims)
135 {
136 // TODO Uncomment this line when GraphInput is ready
137 // _graph_input->shape(dims)
138 _node->shape(dims);
139 return this;
140 }
141
142 private:
143 loco::GraphInput *_input = nullptr;
144 loco::Pull *_node = nullptr;
145 };
146
147 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
148 {
149 auto input_index = ctx->graph()->inputs()->size();
150 auto graph_input = ctx->graph()->inputs()->create();
151
152 auto pull_node = ctx->graph()->nodes()->create<loco::Pull>();
153
154 pull_node->index(input_index);
155
156 loco::link(graph_input, pull_node);
157
158 ctx->stack()->push(pull_node);
159
160 return std::make_unique<Return>(graph_input, pull_node);
161 }
162};
163
164// "OutputLayer" creates both GraphOutput and Push node at once.
165struct OutputLayer final
166{
167 class Return
168 {
169 public:
170 Return(loco::GraphOutput *output, loco::Push *node) : _output{output}, _node{node}
171 {
172 // DO NOTHING
173 }
174
175 public:
176 loco::Push *node(void) { return _node; }
177
178 public:
179 Return *name(const std::string &value)
180 {
181 // TODO Uncomment this line when GraphOutput is ready
182 // _graph_output->shape(dims)
183 _output->name(value);
184 return this;
185 }
186
187 private:
188 loco::GraphOutput *_output = nullptr;
189 loco::Push *_node = nullptr;
190 };
191
192 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
193 {
194 auto output_index = ctx->graph()->outputs()->size();
195 auto graph_output = ctx->graph()->outputs()->create();
196
197 auto push_node = ctx->graph()->nodes()->create<loco::Push>();
198
199 push_node->from(ctx->stack()->pop());
200 push_node->index(output_index);
201
202 loco::link(graph_output, push_node);
203
204 ctx->stack()->push(push_node);
205
206 return std::make_unique<Return>(graph_output, push_node);
207 }
208};
209
210struct ReLULayer final
211{
212 // This "Return" is unnecessary for ReLU as ReLU has no attributes), but
213 // introduced for consistency.
214 class Return
215 {
216 public:
218 {
219 // DO NOTHING
220 }
221
222 public:
223 loco::ReLU *node(void) { return _node; }
224
225 private:
226 loco::ReLU *_node = nullptr;
227 };
228
229 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
230 {
231 auto relu_node = ctx->graph()->nodes()->create<loco::ReLU>();
232
233 relu_node->input(ctx->stack()->pop());
234
235 ctx->stack()->push(relu_node);
236
237 return std::make_unique<Return>(relu_node);
238 }
239};
240
241struct ConstGenLayer final
242{
243 class Return
244 {
245 public:
247 {
248 // DO NOTHING
249 }
250
251 public:
252 loco::ConstGen *node(void) { return _node; }
253
254 private:
255 loco::ConstGen *_node = nullptr;
256 };
257
258 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
259 {
260 auto const_node = ctx->graph()->nodes()->create<loco::ConstGen>();
261
262 ctx->stack()->push(const_node);
263
264 return std::make_unique<Return>(const_node);
265 }
266};
267
269
271{
272 class Return
273 {
274 public:
276 {
277 // DO NOTHING
278 }
279
280 public:
282 {
283 using namespace loco;
284 _node->encoder(std::make_unique<PermutingEncoder<Domain::Feature>>(perm));
285 return this;
286 }
287
288 public:
289 loco::FeatureEncode *node(void) { return _node; }
290
291 private:
292 loco::FeatureEncode *_node;
293 };
294
295 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
296 {
297 auto encode_node = ctx->graph()->nodes()->create<loco::FeatureEncode>();
298
299 encode_node->input(ctx->stack()->pop());
300
301 ctx->stack()->push(encode_node);
302
303 return std::make_unique<Return>(encode_node);
304 }
305};
306
308{
309 class Return
310 {
311 public:
313 {
314 // DO NOTHING
315 }
316
317 public:
319 {
320 using namespace loco;
321 _node->decoder(std::make_unique<PermutingDecoder<Domain::Feature>>(perm));
322 return this;
323 }
324
325 public:
326 loco::FeatureDecode *node(void) { return _node; }
327
328 private:
329 loco::FeatureDecode *_node;
330 };
331
332 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
333 {
334 using namespace loco;
335
336 auto decode_node = ctx->graph()->nodes()->create<FeatureDecode>();
337
338 decode_node->input(ctx->stack()->pop());
339
340 ctx->stack()->push(decode_node);
341
342 return std::make_unique<Return>(decode_node);
343 }
344};
345
347{
348 class Return
349 {
350 public:
352 {
353 // DO NOTHING
354 }
355
356 public:
358 {
359 auto encoder = std::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
360 encoder->perm(perm);
361 _node->encoder(std::move(encoder));
362 return this;
363 }
364
365 public:
366 loco::FilterEncode *node(void) { return _node; }
367
368 private:
369 loco::FilterEncode *_node;
370 };
371
372 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
373 {
374 auto encode_node = ctx->graph()->nodes()->create<loco::FilterEncode>();
375
376 encode_node->input(ctx->stack()->pop());
377
378 ctx->stack()->push(encode_node);
379
380 return std::make_unique<Return>(encode_node);
381 }
382};
383
385{
386 class Return
387 {
388 public:
390 {
391 // DO NOTHING
392 }
393
394 public:
396 {
397 using namespace loco;
398 _node->encoder(std::make_unique<PermutingEncoder<Domain::DepthwiseFilter>>(perm));
399 return this;
400 }
401
402 public:
403 loco::DepthwiseFilterEncode *node(void) { return _node; }
404
405 private:
407 };
408
409 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
410 {
411 auto encode_node = ctx->graph()->nodes()->create<loco::DepthwiseFilterEncode>();
412
413 encode_node->input(ctx->stack()->pop());
414
415 ctx->stack()->push(encode_node);
416
417 return std::make_unique<Return>(encode_node);
418 }
419};
420
422{
423 class Return
424 {
425 public:
427 {
428 // DO NOTHING
429 }
430
431 public:
432 loco::DepthwiseConv2D *node(void) { return _node; }
433
434 private:
436 };
437
438 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
439 {
440 auto depthwiseconv2d_node = ctx->graph()->nodes()->create<loco::DepthwiseConv2D>();
441
442 depthwiseconv2d_node->ker(ctx->stack()->pop());
443 depthwiseconv2d_node->ifm(ctx->stack()->pop());
444
445 ctx->stack()->push(depthwiseconv2d_node);
446
447 return std::make_unique<Return>(depthwiseconv2d_node);
448 }
449};
450
452{
453 class Return
454 {
455 public:
457 {
458 // DO NOTHING
459 }
460
461 public:
462 loco::TransposedConv2D *node(void) { return _node; }
463
464 private:
466 };
467
468 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
469 {
470 auto tr_conv2d_node = ctx->graph()->nodes()->create<loco::TransposedConv2D>();
471
472 tr_conv2d_node->ker(ctx->stack()->pop());
473 tr_conv2d_node->ifm(ctx->stack()->pop());
474
475 ctx->stack()->push(tr_conv2d_node);
476
477 return std::make_unique<Return>(tr_conv2d_node);
478 }
479};
480
482{
483 class Return
484 {
485 public:
487 {
488 // DO NOTHING
489 }
490
491 public:
492 Return *shape(std::initializer_list<uint32_t> dims)
493 {
494 _node->shape(dims);
495 return this;
496 }
497
498 public:
499 loco::FixedReshape *node(void) { return _node; }
500
501 private:
502 loco::FixedReshape *_node = nullptr;
503 };
504
505 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
506 {
507 auto reshape_node = ctx->graph()->nodes()->create<loco::FixedReshape>();
508
509 reshape_node->input(ctx->stack()->pop());
510
511 ctx->stack()->push(reshape_node);
512
513 return std::make_unique<Return>(reshape_node);
514 }
515};
516
518{
519 class Return
520 {
521 public:
523 {
524 // DO NOTHING
525 }
526
527 public:
528 loco::TensorBroadcast *node(void) { return _node; }
529
530 private:
531 loco::TensorBroadcast *_node = nullptr;
532 };
533
534 std::unique_ptr<Return> operator()(GraphBuilder::Context *ctx)
535 {
536 auto broadcast_node = ctx->graph()->nodes()->create<loco::TensorBroadcast>();
537
538 broadcast_node->input(ctx->stack()->pop());
539 ctx->stack()->push(broadcast_node);
540
541 return std::make_unique<Return>(broadcast_node);
542 }
543};
544
545#endif // __GRAPH_BUILDER_H__
loco::ConstGen * node(void)
Return(loco::ConstGen *node)
loco::DepthwiseConv2D * node(void)
Return(loco::DepthwiseConv2D *node)
Return * perm(const loco::Permutation< loco::Domain::DepthwiseFilter > &perm)
Return(loco::DepthwiseFilterEncode *node)
loco::DepthwiseFilterEncode * node(void)
Return(loco::FeatureDecode *node)
Return * perm(const loco::Permutation< loco::Domain::Feature > &perm)
loco::FeatureDecode * node(void)
Return(loco::FeatureEncode *node)
loco::FeatureEncode * node(void)
Return * perm(const loco::Permutation< loco::Domain::Feature > &perm)
Return * perm(const loco::Permutation< loco::Domain::Filter > &perm)
Return(loco::FilterEncode *node)
loco::FilterEncode * node(void)
loco::FixedReshape * node(void)
Return * shape(std::initializer_list< uint32_t > dims)
Return(loco::FixedReshape *node)
loco::Graph * graph(void)
Context(loco::Graph *graph)
Stack * stack(void)
void push(loco::Node *node)
loco::Node * top(void) const
loco::Node * pop(void)
GraphBuilder(loco::Graph *graph)
loco::Node * pop(void)
auto push(Args &&...args) -> decltype(static_cast< Layer * >(nullptr) ->operator()(static_cast< Context * >(nullptr)))
Return * name(const std::string &value)
loco::Pull * node(void)
Return(loco::GraphInput *input, loco::Pull *node)
Return * shape(std::initializer_list< uint32_t > dims)
loco::Push * node(void)
Return * name(const std::string &value)
Return(loco::GraphOutput *output, loco::Push *node)
Return(loco::ReLU *node)
loco::ReLU * node(void)
Return(loco::TensorBroadcast *node)
loco::TensorBroadcast * node(void)
Return(loco::TransposedConv2D *node)
loco::TransposedConv2D * node(void)
Create a value from constant byte array.
Definition Nodes.h:218
Depthwise 2D Convolution.
Definition Nodes.h:582
Node * ker(void) const
Definition Nodes.h:587
Create a depthwise filter from a tensor.
Definition Nodes.h:456
Node * input(void) const
Definition Nodes.h:458
DepthwiseFilterEncoder * encoder(void) const
Definition Nodes.h:462
Create a tensor from a feature map.
Definition Nodes.h:399
Node * input(void) const
Definition Nodes.h:401
FeatureDecoder * decoder(void) const
Definition Nodes.h:405
Create a feature map from a tensor.
Definition Nodes.h:380
FeatureEncoder * encoder(void) const
Definition Nodes.h:386
Node * input(void) const
Definition Nodes.h:382
Create a filter from a tensor.
Definition Nodes.h:418
Node * input(void) const
Definition Nodes.h:420
FilterEncoder * encoder(void) const
Definition Nodes.h:424
A neural network graph.
Definition Graph.h:161
InputContext * inputs(void)
Definition Graph.h:220
NodeContext * nodes(void)
Definition Graph.h:218
OutputContext * outputs(void)
Definition Graph.h:222
Graph-level Input Metadata.
Definition Graph.h:107
Graph-level Output Metadata.
Definition Graph.h:135
Logical unit of computation.
Definition Node.h:54
Derived * create(Args &&...args)
Definition NodePool.h:37
uint32_t size(void) const
Return the number of objects.
Definition ObjectPool.h:38
Create a value from user data.
Definition Nodes.h:96
void index(const GraphInputIndex &index)
Definition Nodes.cpp:90
Make a value visible to user.
Definition Nodes.h:53
Node * from(void) const
Definition Nodes.h:58
void index(const GraphOutputIndex &index)
Definition Nodes.cpp:52
Create a new value that rectifies its input.
Definition Nodes.h:159
Node * input(void) const
Definition Nodes.h:164
Reshape a tensor to another tensor whose shape is known at compile time.
Definition Nodes.h:517
Duplicate elements along specified axes.
Definition Nodes.h:980
Node * input(void) const
Definition Nodes.h:985
2D Transposed Convolution
Definition Nodes.h:688
Node * ker(void) const
Definition Nodes.h:693
void link(GraphOutput *, Push *push)
Definition Nodes.cpp:65
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
std::unique_ptr< Return > operator()(GraphBuilder::Context *ctx)
GraphInput * create(void)
Definition Graph.cpp:52
GraphOutput * create(void)
Definition Graph.cpp:54