Compute Library
 20.02.1
GraphBuilder.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2020 ARM Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
25 
30 
32 
33 namespace arm_compute
34 {
35 namespace graph
36 {
37 namespace
38 {
39 inline void check_nodeidx_pair(const NodeIdxPair &pair, const Graph &g)
40 {
41  ARM_COMPUTE_UNUSED(pair);
43  ARM_COMPUTE_ERROR_ON((pair.node_id >= g.nodes().size()) || (g.node((pair).node_id) == nullptr) || (pair.index >= g.node(pair.node_id)->num_outputs()));
44 }
45 
46 Status set_node_params(Graph &g, NodeID nid, NodeParams &params)
47 {
48  INode *node = g.node(nid);
50 
51  node->set_common_node_parameters(params);
52 
53  return Status{};
54 }
55 
56 Status set_accessor_on_node(Graph &g, NodeID nid, bool is_output, size_t idx, ITensorAccessorUPtr accessor)
57 {
58  INode *node = g.node(nid);
60 
61  Tensor *tensor = is_output ? node->output(idx) : node->input(idx);
63 
64  tensor->set_accessor(std::move(accessor));
65 
66  return Status{};
67 }
68 
69 NodeID add_const_node_with_name(Graph &g, NodeParams params, const std::string &name, const TensorDescriptor &desc, ITensorAccessorUPtr accessor)
70 {
71  params.name = params.name.empty() ? "" : params.name + name;
72  auto nid = GraphBuilder::add_const_node(g, params, desc, std::move(accessor));
73  set_node_params(g, nid, params);
74  return nid;
75 }
76 
77 template <typename NT, typename... Args>
78 NodeID create_simple_single_input_output_node(Graph &g, NodeParams &params, NodeIdxPair input, Args &&... args)
79 {
80  check_nodeidx_pair(input, g);
81 
82  NodeID nid = g.add_node<NT>(std::forward<Args>(args)...);
83  g.add_connection(input.node_id, input.index, nid, 0);
84  set_node_params(g, nid, params);
85 
86  return nid;
87 }
88 
89 template <typename NT, typename... Args>
90 NodeID create_simple_multiple_input_single_output_node(Graph &g, NodeParams &params, const std::vector<NodeIdxPair> &inputs, Args &&... args)
91 {
92  ARM_COMPUTE_ERROR_ON(inputs.size() == 0);
93 
94  NodeID nid = g.add_node<NT>(std::forward<Args>(args)...);
95 
96  unsigned int i = 0;
97  for(const auto &input : inputs)
98  {
99  check_nodeidx_pair(input, g);
100  g.add_connection(input.node_id, input.index, nid, i++);
101  }
102  set_node_params(g, nid, params);
103 
104  return nid;
105 }
106 } // namespace
107 
109 {
110  auto nid = g.add_node<ConstNode>(desc);
111  set_node_params(g, nid, params);
112  set_accessor_on_node(g, nid, true, 0, std::move(accessor));
113  return nid;
114 }
115 
117 {
118  auto nid = g.add_node<InputNode>(desc);
119  set_node_params(g, nid, params);
120  set_accessor_on_node(g, nid, true, 0, std::move(accessor));
121  return nid;
122 }
123 
125 {
126  check_nodeidx_pair(input, g);
127 
128  NodeID nid = g.add_node<OutputNode>();
129  g.add_connection(input.node_id, input.index, nid, 0);
130  set_node_params(g, nid, params);
131  set_accessor_on_node(g, nid, false, 0, std::move(accessor));
132 
133  return nid;
134 }
135 
137  const QuantizationInfo &out_quant_info)
138 {
139  return create_simple_single_input_output_node<ActivationLayerNode>(g, params, input, act_info, out_quant_info);
140 }
141 
143  ITensorAccessorUPtr mean_accessor, ITensorAccessorUPtr var_accessor,
144  ITensorAccessorUPtr beta_accessor, ITensorAccessorUPtr gamma_accessor)
145 {
146  check_nodeidx_pair(input, g);
147 
148  bool has_beta = (beta_accessor != nullptr);
149  bool has_gamma = (gamma_accessor != nullptr);
150 
151  // Get input tensor descriptor
152  const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]);
153 
154  // Calculate Common Descriptor
155  TensorDescriptor common_desc = input_tensor_desc;
156  common_desc.shape = TensorShape(get_dimension_size(input_tensor_desc, DataLayoutDimension::CHANNEL));
157 
158  // Create mean and var nodes
159  auto mean_nid = add_const_node_with_name(g, params, "Mean", common_desc, std::move(mean_accessor));
160  auto var_nid = add_const_node_with_name(g, params, "Variance", common_desc, std::move(var_accessor));
161 
162  // Create beta node
163  NodeID beta_nid = EmptyNodeID;
164  if(has_beta)
165  {
166  beta_nid = add_const_node_with_name(g, params, "Beta", common_desc, std::move(beta_accessor));
167  }
168 
169  // Create gamma node
170  NodeID gamma_nid = EmptyNodeID;
171  if(has_gamma)
172  {
173  gamma_nid = add_const_node_with_name(g, params, "Gamma", common_desc, std::move(gamma_accessor));
174  }
175 
176  // Create batch normalization node and add connections
177  NodeID batch_norm_nid = g.add_node<BatchNormalizationLayerNode>(epsilon);
178  g.add_connection(input.node_id, input.index, batch_norm_nid, 0);
179  g.add_connection(mean_nid, 0, batch_norm_nid, 1);
180  g.add_connection(var_nid, 0, batch_norm_nid, 2);
181  if(has_beta)
182  {
183  g.add_connection(beta_nid, 0, batch_norm_nid, 3);
184  }
185  if(has_gamma)
186  {
187  g.add_connection(gamma_nid, 0, batch_norm_nid, 4);
188  }
189  set_node_params(g, batch_norm_nid, params);
190 
191  return batch_norm_nid;
192 }
193 
195 {
196  check_nodeidx_pair(input, g);
197  check_nodeidx_pair(deltas, g);
198 
200 
201  g.add_connection(input.node_id, input.index, nid, 0);
202  g.add_connection(deltas.node_id, deltas.index, nid, 1);
203 
204  set_node_params(g, nid, params);
205  return nid;
206 }
207 
209 {
210  return create_simple_single_input_output_node<ChannelShuffleLayerNode>(g, params, input, num_groups);
211 }
212 
214  Size2D kernel_spatial_extend, unsigned int depth, PadStrideInfo conv_info,
215  unsigned int num_groups, ConvolutionMethod method, FastMathHint fast_math_hint,
216  ITensorAccessorUPtr weights_accessor, ITensorAccessorUPtr bias_accessor,
217  const QuantizationInfo &weights_quant_info,
218  const QuantizationInfo &out_quant_info)
219 {
220  check_nodeidx_pair(input, g);
221  ARM_COMPUTE_ERROR_ON(depth == 0);
222  ARM_COMPUTE_ERROR_ON((kernel_spatial_extend.width == 0) || (kernel_spatial_extend.height == 0));
223 
224  bool has_bias = (bias_accessor != nullptr);
225 
226  // Get input tensor descriptor
227  const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]);
228  const DataLayout input_data_layout = input_tensor_desc.layout;
229 
230  // Create weights node
231  TensorDescriptor w_desc = input_tensor_desc;
232  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::WIDTH), kernel_spatial_extend.width);
233  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::HEIGHT), kernel_spatial_extend.height);
234  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::CHANNEL),
236  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::BATCHES), depth);
237  if(!weights_quant_info.empty())
238  {
239  w_desc.quant_info = weights_quant_info;
240  }
241 
242  NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor));
243 
244  // Create bias nodes
245  NodeID b_nid = EmptyNodeID;
246  if(has_bias)
247  {
248  TensorDescriptor b_desc = input_tensor_desc;
249  b_desc.shape = TensorShape(depth);
250  if(is_data_type_quantized_asymmetric(input_tensor_desc.data_type))
251  {
252  b_desc.data_type = DataType::S32;
253  }
254  b_nid = add_const_node_with_name(g, params, "Bias", b_desc, std::move(bias_accessor));
255  }
256 
257  // Create convolution node and connect
258  NodeID conv_nid = g.add_node<ConvolutionLayerNode>(conv_info, num_groups, method, fast_math_hint, out_quant_info);
259  g.add_connection(input.node_id, input.index, conv_nid, 0);
260  g.add_connection(w_nid, 0, conv_nid, 1);
261  if(has_bias)
262  {
263  g.add_connection(b_nid, 0, conv_nid, 2);
264  }
265  set_node_params(g, conv_nid, params);
266 
267  return conv_nid;
268 }
269 
271  Size2D kernel_spatial_extend, unsigned int depth, PadStrideInfo deconv_info,
272  ITensorAccessorUPtr weights_accessor,
273  ITensorAccessorUPtr bias_accessor)
274 {
275  check_nodeidx_pair(input, g);
276  ARM_COMPUTE_ERROR_ON(depth == 0);
277  ARM_COMPUTE_ERROR_ON((kernel_spatial_extend.width == 0) || (kernel_spatial_extend.height == 0));
278 
279  bool has_bias = (bias_accessor != nullptr);
280 
281  // Get input tensor descriptor
282  const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]);
283  const DataLayout input_data_layout = input_tensor_desc.layout;
284 
285  // Create weights node
286  TensorDescriptor w_desc = input_tensor_desc;
287  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::WIDTH), kernel_spatial_extend.width);
288  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::HEIGHT), kernel_spatial_extend.height);
289  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::CHANNEL),
291  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::BATCHES), depth);
292 
293  NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor));
294 
295  // Create bias nodes
296  NodeID b_nid = EmptyNodeID;
297  if(has_bias)
298  {
299  TensorDescriptor b_desc = input_tensor_desc;
300  b_desc.shape = TensorShape(depth);
301  if(is_data_type_quantized_asymmetric(input_tensor_desc.data_type))
302  {
303  b_desc.data_type = DataType::S32;
304  }
305  b_nid = add_const_node_with_name(g, params, "Bias", b_desc, std::move(bias_accessor));
306  }
307 
308  // Create convolution node and connect
309  NodeID deconv_nid = g.add_node<DeconvolutionLayerNode>(deconv_info);
310  g.add_connection(input.node_id, input.index, deconv_nid, 0);
311  g.add_connection(w_nid, 0, deconv_nid, 1);
312  if(has_bias)
313  {
314  g.add_connection(b_nid, 0, deconv_nid, 2);
315  }
316  set_node_params(g, deconv_nid, params);
317 
318  return deconv_nid;
319 }
320 
321 NodeID GraphBuilder::add_concatenate_node(Graph &g, NodeParams params, const std::vector<NodeIdxPair> &inputs, const descriptors::ConcatLayerDescriptor &concat_descriptor)
322 {
323  return create_simple_multiple_input_single_output_node<ConcatenateLayerNode>(g, params, inputs, inputs.size(), concat_descriptor);
324 }
325 
327  PadStrideInfo conv_info, int depth_multiplier, DepthwiseConvolutionMethod method,
328  ITensorAccessorUPtr weights_accessor, ITensorAccessorUPtr bias_accessor, const QuantizationInfo &quant_info, const QuantizationInfo &out_quant_info)
329 {
330  check_nodeidx_pair(input, g);
331  ARM_COMPUTE_ERROR_ON((kernel_spatial_extend.width == 0) || (kernel_spatial_extend.height == 0));
332 
333  bool has_bias = (bias_accessor != nullptr);
334 
335  // Get input tensor descriptor
336  const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]);
337  const DataLayout input_data_layout = input_tensor_desc.layout;
338 
339  // Create weights node
340  TensorDescriptor w_desc = input_tensor_desc;
341  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::WIDTH), kernel_spatial_extend.width);
342  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::HEIGHT), kernel_spatial_extend.height);
343  w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::CHANNEL),
344  get_dimension_size(input_tensor_desc, DataLayoutDimension::CHANNEL) * depth_multiplier);
345  if(!quant_info.empty())
346  {
347  w_desc.quant_info = quant_info;
348  }
349 
350  NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor));
351 
352  // Create bias nodes
353  NodeID b_nid = EmptyNodeID;
354  if(has_bias)
355  {
356  TensorDescriptor b_desc = input_tensor_desc;
357  b_desc.shape = TensorShape(get_dimension_size(input_tensor_desc, DataLayoutDimension::CHANNEL) * depth_multiplier);
358 
360  {
361  b_desc.data_type = DataType::S32;
362  }
363 
364  b_nid = add_const_node_with_name(g, params, "Bias", b_desc, std::move(bias_accessor));
365  }
366 
367  // Create convolution node and connect
368  NodeID conv_nid = g.add_node<DepthwiseConvolutionLayerNode>(conv_info, depth_multiplier, method, out_quant_info);
369  g.add_connection(input.node_id, input.index, conv_nid, 0);
370  g.add_connection(w_nid, 0, conv_nid, 1);
371  if(has_bias)
372  {
373  g.add_connection(b_nid, 0, conv_nid, 2);
374  }
375  set_node_params(g, conv_nid, params);
376 
377  return conv_nid;
378 }
380 {
381  return create_simple_single_input_output_node<DequantizationLayerNode>(g, params, input);
382 }
383 
385 {
386  check_nodeidx_pair(input_loc, g);
387  check_nodeidx_pair(input_conf, g);
388  check_nodeidx_pair(input_priorbox, g);
389 
390  // Create detection_output node and connect
391  NodeID detect_nid = g.add_node<DetectionOutputLayerNode>(detect_info);
392  g.add_connection(input_loc.node_id, input_loc.index, detect_nid, 0);
393  g.add_connection(input_conf.node_id, input_conf.index, detect_nid, 1);
394  g.add_connection(input_priorbox.node_id, input_priorbox.index, detect_nid, 2);
395 
396  set_node_params(g, detect_nid, params);
397 
398  return detect_nid;
399 }
400 
401 NodeID GraphBuilder::add_detection_post_process_node(Graph &g, NodeParams params, NodeIdxPair input_box_encoding, NodeIdxPair input_class_prediction, const DetectionPostProcessLayerInfo &detect_info,
402  ITensorAccessorUPtr anchors_accessor, const QuantizationInfo &anchor_quant_info)
403 {
404  check_nodeidx_pair(input_box_encoding, g);
405  check_nodeidx_pair(input_class_prediction, g);
406 
407  // Get input tensor descriptor
408  const TensorDescriptor input_box_encoding_tensor_desc = get_tensor_descriptor(g, g.node(input_box_encoding.node_id)->outputs()[0]);
409 
410  // Calculate anchor descriptor
411  TensorDescriptor anchor_desc = input_box_encoding_tensor_desc;
412  if(!anchor_quant_info.empty())
413  {
414  anchor_desc.quant_info = anchor_quant_info;
415  }
416 
417  // Create anchors nodes
418  auto anchors_nid = add_const_node_with_name(g, params, "Anchors", anchor_desc, std::move(anchors_accessor));
419 
420  // Create detection_output node and connect
421  NodeID detect_nid = g.add_node<DetectionPostProcessLayerNode>(detect_info);
422  g.add_connection(input_box_encoding.node_id, input_box_encoding.index, detect_nid, 0);
423  g.add_connection(input_class_prediction.node_id, input_class_prediction.index, detect_nid, 1);
424  g.add_connection(anchors_nid, 0, detect_nid, 2);
425 
426  set_node_params(g, detect_nid, params);
427 
428  return detect_nid;
429 }
430 
432 {
433  return create_simple_single_input_output_node<DummyNode>(g, params, input, shape);
434 }
435 
437 {
438  check_nodeidx_pair(input0, g);
439  check_nodeidx_pair(input1, g);
440 
441  NodeID nid = g.add_node<EltwiseLayerNode>(operation);
442 
443  g.add_connection(input0.node_id, input0.index, nid, 0);
444  g.add_connection(input1.node_id, input1.index, nid, 1);
445 
446  set_node_params(g, nid, params);
447 
448  return nid;
449 }
450 
452 {
453  return create_simple_single_input_output_node<FlattenLayerNode>(g, params, input);
454 }
455 
457  NodeID weights_nid, NodeID bias_nid,
458  const FullyConnectedLayerInfo fc_info, const QuantizationInfo &out_quant_info)
459 {
460  check_nodeidx_pair(input, g);
461  ARM_COMPUTE_ERROR_ON(num_outputs == 0);
462  ARM_COMPUTE_ERROR_ON(weights_nid == EmptyNodeID);
463 
464  const bool has_bias = (bias_nid != EmptyNodeID);
465 
466  // Get input tensor descriptor
467  const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]);
468 
469  // Create fully connected node and connect
470  NodeID fc_nid = g.add_node<FullyConnectedLayerNode>(num_outputs, out_quant_info, fc_info);
471  g.add_connection(input.node_id, input.index, fc_nid, 0);
472  g.add_connection(weights_nid, 0, fc_nid, 1);
473  if(has_bias)
474  {
475  g.add_connection(bias_nid, 0, fc_nid, 2);
476  }
477 
478  set_node_params(g, fc_nid, params);
479 
480  return fc_nid;
481 }
482 
484  ITensorAccessorUPtr weights_accessor, ITensorAccessorUPtr bias_accessor,
485  const FullyConnectedLayerInfo fc_info,
486  const QuantizationInfo &weights_quant_info, const QuantizationInfo &out_quant_info)
487 {
488  check_nodeidx_pair(input, g);
489  ARM_COMPUTE_ERROR_ON(num_outputs == 0);
490 
491  bool has_bias = (bias_accessor != nullptr);
492 
493  // Get input tensor descriptor
494  const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]);
495 
496  // Create weights node
497  TensorDescriptor w_desc = FullyConnectedLayerNode::compute_weights_descriptor(input_tensor_desc, num_outputs, fc_info, weights_quant_info);
498  NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor));
499 
500  // Create bias nodes
501  NodeID b_nid = EmptyNodeID;
502  if(has_bias)
503  {
504  TensorDescriptor b_desc = input_tensor_desc;
505  b_desc.shape = TensorShape(num_outputs);
506  if(is_data_type_quantized_asymmetric(input_tensor_desc.data_type))
507  {
508  b_desc.data_type = DataType::S32;
509  }
510  b_nid = add_const_node_with_name(g, params, "Bias", b_desc, std::move(bias_accessor));
511  }
512 
513  // Create fully connected node and connect
514  NodeID fc_nid = g.add_node<FullyConnectedLayerNode>(num_outputs, out_quant_info, fc_info);
515  g.add_connection(input.node_id, input.index, fc_nid, 0);
516  g.add_connection(w_nid, 0, fc_nid, 1);
517  if(has_bias)
518  {
519  g.add_connection(b_nid, 0, fc_nid, 2);
520  }
521 
522  set_node_params(g, fc_nid, params);
523 
524  return fc_nid;
525 }
526 
528 {
529  check_nodeidx_pair(scores, g);
530  check_nodeidx_pair(deltas, g);
531  check_nodeidx_pair(anchors, g);
532 
534 
535  g.add_connection(scores.node_id, scores.index, nid, 0);
536  g.add_connection(deltas.node_id, deltas.index, nid, 1);
537  g.add_connection(anchors.node_id, anchors.index, nid, 2);
538 
539  set_node_params(g, nid, params);
540  return nid;
541 }
542 
544 {
545  return create_simple_single_input_output_node<NormalizationLayerNode>(g, params, input, norm_info);
546 }
547 
549  ITensorAccessorUPtr mean_accessor, ITensorAccessorUPtr std_accessor)
550 {
551  check_nodeidx_pair(input, g);
552 
553  // Get input tensor descriptor
554  const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]);
555 
556  // Calculate Common Descriptor
557  TensorDescriptor common_desc = input_tensor_desc;
558  common_desc.shape = TensorShape(get_dimension_size(input_tensor_desc, DataLayoutDimension::CHANNEL));
559 
560  // Create mean and std nodes
561  auto mean_nid = add_const_node_with_name(g, params, "Mean", common_desc, std::move(mean_accessor));
562  auto std_nid = add_const_node_with_name(g, params, "Std", common_desc, std::move(std_accessor));
563 
564  // Create normalize planar YUV node and add connections
565  NodeID norm_planar_yuv_nid = g.add_node<NormalizePlanarYUVLayerNode>();
566  g.add_connection(input.node_id, input.index, norm_planar_yuv_nid, 0);
567  g.add_connection(mean_nid, 0, norm_planar_yuv_nid, 1);
568  g.add_connection(std_nid, 0, norm_planar_yuv_nid, 2);
569  set_node_params(g, norm_planar_yuv_nid, params);
570 
571  return norm_planar_yuv_nid;
572 }
573 
575 {
576  return create_simple_single_input_output_node<PadLayerNode>(g, params, input, padding);
577 }
578 
580 {
581  return create_simple_single_input_output_node<PermuteLayerNode>(g, params, input, perm, layout);
582 }
583 
585 {
586  check_nodeidx_pair(input, g);
587  check_nodeidx_pair(alpha, g);
588 
589  NodeID prelu_nid = g.add_node<PReluLayerNode>();
590  g.add_connection(input.node_id, input.index, prelu_nid, 0);
591  g.add_connection(alpha.node_id, alpha.index, prelu_nid, 1);
592 
593  set_node_params(g, prelu_nid, params);
594 
595  return prelu_nid;
596 }
597 
599 {
600  return create_simple_single_input_output_node<PoolingLayerNode>(g, params, input, pool_info);
601 }
602 
603 NodeID GraphBuilder::add_print_node(Graph &g, NodeParams params, NodeIdxPair input, std::ostream &stream, const IOFormatInfo &format_info, const std::function<ITensor *(ITensor *)> transform)
604 {
605  return create_simple_single_input_output_node<PrintLayerNode>(g, params, input, stream, format_info, transform);
606 }
607 
609 {
610  check_nodeidx_pair(input0, g);
611  check_nodeidx_pair(input1, g);
612 
613  // Create priorbox node and connect
614  NodeID prior_nid = g.add_node<PriorBoxLayerNode>(prior_info);
615  g.add_connection(input0.node_id, input0.index, prior_nid, 0);
616  g.add_connection(input1.node_id, input1.index, prior_nid, 1);
617 
618  set_node_params(g, prior_nid, params);
619 
620  return prior_nid;
621 }
622 
624 {
625  return create_simple_single_input_output_node<QuantizationLayerNode>(g, params, input, out_quant_info);
626 }
627 
629 {
630  return create_simple_single_input_output_node<ReorgLayerNode>(g, params, input, stride);
631 }
632 
634 {
635  return create_simple_single_input_output_node<ReshapeLayerNode>(g, params, input, shape);
636 }
637 
639  float width_scale, float height_scale)
640 {
641  return create_simple_single_input_output_node<ResizeLayerNode>(g, params, input, policy, width_scale, height_scale);
642 }
643 
645 {
646  check_nodeidx_pair(input, g);
647  check_nodeidx_pair(rois, g);
648 
649  NodeID nid = g.add_node<ROIAlignLayerNode>(pool_info);
650 
651  g.add_connection(input.node_id, input.index, nid, 0);
652  g.add_connection(rois.node_id, rois.index, nid, 1);
653 
654  set_node_params(g, nid, params);
655  return nid;
656 }
657 
659 {
660  check_nodeidx_pair(input, g);
661 
662  // Get input tensor descriptor
663  const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]);
664  const DataLayout input_data_layout = input_tensor_desc.layout;
665 
666  // Create mul node
667  TensorDescriptor mul_desc = input_tensor_desc;
668  const size_t C = input_tensor_desc.shape[get_dimension_idx(input_data_layout, DataLayoutDimension::CHANNEL)];
669  mul_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::WIDTH), 1);
670  mul_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::HEIGHT), 1);
671  mul_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::CHANNEL), C);
672  NodeID mul_const_nid = add_const_node_with_name(g, params, "Mul", mul_desc, std::move(mul_accessor));
673  NodeIdxPair mul_const_nidxp = { mul_const_nid, 0 };
674 
675  // Create add node
676  TensorDescriptor add_desc = mul_desc;
677  NodeID add_const_nid = add_const_node_with_name(g, params, "Add", add_desc, std::move(add_accessor));
678  NodeIdxPair add_const_nidxp = { add_const_nid, 0 };
679 
680  // Create node and connect
681  NodeID mul_node = GraphBuilder::add_elementwise_node(g, params, input, mul_const_nidxp, EltwiseOperation::Mul);
682  NodeIdxPair mulnode_nidxp = { mul_node, 0 };
683  NodeID add_node = GraphBuilder::add_elementwise_node(g, params, mulnode_nidxp, add_const_nidxp, EltwiseOperation::Add);
684 
685  return add_node;
686 }
687 
689 {
690  return create_simple_single_input_output_node<SoftmaxLayerNode>(g, params, input, beta);
691 }
692 
694 {
695  return create_simple_single_input_output_node<SliceLayerNode>(g, params, input, starts, ends);
696 }
697 
698 NodeID GraphBuilder::add_split_node(Graph &g, NodeParams params, NodeIdxPair input, unsigned int num_splits, unsigned int axis)
699 {
700  return create_simple_single_input_output_node<SplitLayerNode>(g, params, input, num_splits, axis);
701 }
702 
703 NodeID GraphBuilder::add_stack_node(Graph &g, NodeParams params, const std::vector<NodeIdxPair> &inputs, int axis)
704 {
705  return create_simple_multiple_input_single_output_node<StackLayerNode>(g, params, inputs, inputs.size(), axis);
706 }
707 
709 {
710  return create_simple_single_input_output_node<UpsampleLayerNode>(g, params, input, info, upsampling_policy);
711 }
712 
714 {
715  return create_simple_single_input_output_node<YOLOLayerNode>(g, params, input, act_info, num_classes);
716 }
717 } // namespace graph
718 } // namespace arm_compute
TensorDescriptor get_tensor_descriptor(const Graph &g, TensorID tid)
Returns the tensor descriptor of a given tensor.
Definition: Utils.h:50
Common node parameters.
Definition: Types.h:196
static NodeID add_yolo_node(Graph &g, NodeParams params, NodeIdxPair input, ActivationLayerInfo act_info, int32_t num_classes)
Adds a yolo layer to the graph.
NodeID node_id
Node ID.
Definition: Types.h:191
static NodeID add_split_node(Graph &g, NodeParams params, NodeIdxPair input, unsigned int num_splits, unsigned int axis=0)
Adds a split node to the graph.
InterpolationPolicy
Interpolation method.
Definition: Types.h:366
static NodeID add_quantization_node(Graph &g, NodeParams params, NodeIdxPair input, const QuantizationInfo &out_quant_info)
Adds a quantization layer node to the graph.
static NodeID add_batch_normalization_node(Graph &g, NodeParams params, NodeIdxPair input, float epsilon, ITensorAccessorUPtr mean_accessor=nullptr, ITensorAccessorUPtr var_accessor=nullptr, ITensorAccessorUPtr beta_accessor=nullptr, ITensorAccessorUPtr gamma_accessor=nullptr)
Adds a batch normalization layer node to the graph.
Generate Proposals Information class.
Definition: Types.h:1417
Shape of a tensor.
Definition: TensorShape.h:39
EltwiseOperation
Supported Element-wise operations.
Definition: Types.h:100
static NodeID add_input_node(Graph &g, NodeParams params, const TensorDescriptor &desc, ITensorAccessorUPtr accessor=nullptr)
Adds an input layer node to the graph.
size_t get_dimension_size(const TensorDescriptor &descriptor, const DataLayoutDimension data_layout_dimension)
Get size of a tensor's given dimension depending on its layout.
Definition: Utils.cpp:123
std::vector< PaddingInfo > PaddingList
List of padding information.
Definition: Types.h:455
static NodeID add_prelu_node(Graph &g, NodeParams params, NodeIdxPair input, NodeIdxPair alpha)
Adds a prelu layer node to the graph.
NodeID add_node(Ts &&... args)
Adds a node to the graph.
Definition: Graph.h:235
static NodeID add_resize_node(Graph &g, NodeParams params, NodeIdxPair input, InterpolationPolicy policy, float width_scale, float height_scale)
Adds a resize layer node to the graph.
static NodeID add_activation_node(Graph &g, NodeParams params, NodeIdxPair input, ActivationLayerInfo act_info, const QuantizationInfo &out_quant_info=QuantizationInfo())
Adds an activation layer node to the graph.
static NodeID add_normalization_node(Graph &g, NodeParams params, NodeIdxPair input, NormalizationLayerInfo norm_info)
Adds a normalization layer node to the graph.
static NodeID add_permute_node(Graph &g, NodeParams params, NodeIdxPair input, PermutationVector perm, DataLayout layout=DataLayout::UNKNOWN)
Adds a permute layer node to the graph.
Normalization Layer Information class.
Definition: Types.h:1677
static NodeID add_pad_node(Graph &g, NodeParams params, NodeIdxPair input, PaddingList padding)
Adds a pad layer node to the graph.
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
Fully connected layer info.
Definition: Types.h:803
std::unique_ptr< ITensorAccessor > ITensorAccessorUPtr
static NodeID add_bounding_box_transform_node(Graph &g, NodeParams params, NodeIdxPair input, NodeIdxPair deltas, BoundingBoxTransformInfo info)
Adds a bounding box transform layer node to the graph.
static NodeID add_reshape_node(Graph &g, NodeParams params, NodeIdxPair input, TensorShape shape)
Adds a reshape layer node to the graph.
#define ARM_COMPUTE_RETURN_ERROR_ON(cond)
If the condition is true, an error is returned.
Definition: Error.h:296
Activation Layer Information class.
Definition: Types.h:1615
static NodeID add_priorbox_node(Graph &g, NodeParams params, NodeIdxPair input0, NodeIdxPair input1, const PriorBoxLayerInfo &prior_info)
Adds a priorbox layer node to the graph.
Interface for NEON tensor.
Definition: ITensor.h:36
static NodeID add_concatenate_node(Graph &g, NodeParams params, const std::vector< NodeIdxPair > &inputs, const descriptors::ConcatLayerDescriptor &concat_descriptor)
Adds a depth concatenate node to the graph.
static NodeID add_generate_proposals_node(Graph &g, NodeParams params, NodeIdxPair scores, NodeIdxPair deltas, NodeIdxPair anchors, GenerateProposalsInfo info)
Adds a generate proposals layer node to the graph.
static NodeID add_slice_node(Graph &g, NodeParams params, NodeIdxPair input, Coordinates &starts, Coordinates &ends)
Adds a slice node to the graph.
static NodeID add_deconvolution_node(Graph &g, NodeParams params, NodeIdxPair input, Size2D kernel_spatial_extend, unsigned int depth, PadStrideInfo deconv_info, ITensorAccessorUPtr weights_accessor=nullptr, ITensorAccessorUPtr bias_accessor=nullptr)
Adds a deconvolution layer node to the graph.
static NodeID add_convolution_node(Graph &g, NodeParams params, NodeIdxPair input, Size2D kernel_spatial_extend, unsigned int depth, PadStrideInfo conv_info, unsigned int num_groups=1, ConvolutionMethod method=ConvolutionMethod::Default, FastMathHint fast_math_hint=FastMathHint::Disabled, ITensorAccessorUPtr weights_accessor=nullptr, ITensorAccessorUPtr bias_accessor=nullptr, const QuantizationInfo &weights_quant_info=QuantizationInfo(), const QuantizationInfo &out_quant_info=QuantizationInfo())
Adds a convolution layer node to the graph.
Copyright (c) 2017-2020 ARM Limited.
size_t height
Height of the image region or rectangle.
Definition: Size2D.h:93
static NodeID add_upsample_node(Graph &g, NodeParams params, NodeIdxPair input, Size2D info, InterpolationPolicy upsampling_policy)
Adds an upsample layer to the graph.
static NodeID add_detection_output_node(Graph &g, NodeParams params, NodeIdxPair input_loc, NodeIdxPair input_conf, NodeIdxPair input_priorbox, const DetectionOutputLayerInfo &detect_info)
Adds a detection output layer node to the graph.
1 channel, 1 S32 per channel
Quantization information.
QuantizationInfo quant_info
Quantization info.
static NodeID add_print_node(Graph &g, NodeParams params, NodeIdxPair input, std::ostream &stream, const IOFormatInfo &format_info=IOFormatInfo(), const std::function< ITensor *(ITensor *)> transform=nullptr)
Adds a print layer node to the graph.
static NodeID add_stack_node(Graph &g, NodeParams params, const std::vector< NodeIdxPair > &inputs, int axis)
Adds a stack layer node to the graph.
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
static NodeID add_elementwise_node(Graph &g, NodeParams params, NodeIdxPair input0, NodeIdxPair input1, EltwiseOperation operation)
Adds an element-wise layer node to the graph.
IO formatting information class.
Definition: Types.h:2177
static NodeID add_reorg_node(Graph &g, NodeParams params, NodeIdxPair input, int stride)
Adds a reorg layer node to the graph.
const unsigned int num_groups
Definition: Im2Col.cpp:148
DepthwiseConvolutionMethod
Supported Depthwise Convolution layer methods.
Definition: Types.h:117
Coordinates of an item.
Definition: Coordinates.h:37
Pooling Layer Information struct.
Definition: Types.h:1211
Output Layer node.
Definition: OutputNode.h:34
static NodeID add_roi_align_node(Graph &g, NodeParams params, NodeIdxPair input, NodeIdxPair rois, ROIPoolingLayerInfo pool_info)
Adds a ROI align layer node to the graph.
PriorBox layer info.
Definition: Types.h:836
Padding and stride information class.
Definition: Types.h:686
const std::vector< TensorID > & outputs() const
Returns outputs of the node.
Definition: INode.cpp:122
EdgeID add_connection(NodeID source, size_t source_idx, NodeID sink, size_t sink_idx)
Adds a connection between two nodes.
Definition: Graph.cpp:69
Bounding Box Transform information class.
Definition: Types.h:1548
static NodeID add_dummy_node(Graph &g, NodeParams params, NodeIdxPair input, TensorShape shape)
Adds a Dummy node to the graph.
static NodeID add_dequantization_node(Graph &g, NodeParams params, NodeIdxPair input)
Adds a dequantization node to the graph.
static NodeID add_normalize_planar_yuv_node(Graph &g, NodeParams params, NodeIdxPair input, ITensorAccessorUPtr mean_accessor=nullptr, ITensorAccessorUPtr std_accessor=nullptr)
Adds a normalize planar YUV layer node to the graph.
NodeID-index struct.
Definition: Types.h:189
FastMathHint
Enable or disable fast math for Convolution layer.
Definition: Types.h:125
bool is_data_type_quantized_asymmetric(DataType dt)
Check if a given data type is of asymmetric quantized type.
Definition: Utils.h:1139
Input Layer node.
Definition: InputNode.h:34
static NodeID add_channel_shuffle_node(Graph &g, NodeParams params, NodeIdxPair input, unsigned int num_groups)
Adds an channel shuffle layer node to the graph.
Strides of an item in bytes.
Definition: Strides.h:37
Graph class.
Definition: Graph.h:53
Detection Output layer info.
Definition: Types.h:973
DetectionPostProcess Layer node.
static NodeID add_detection_post_process_node(Graph &g, NodeParams params, NodeIdxPair input_box_encoding, NodeIdxPair input_class_prediction, const DetectionPostProcessLayerInfo &detect_info, ITensorAccessorUPtr anchors_accessor=nullptr, const QuantizationInfo &anchor_quant_info=QuantizationInfo())
Adds a detection post process layer node to the graph.
unsigned int NodeID
Definition: Types.h:64
static NodeID add_softmax_node(Graph &g, NodeParams params, NodeIdxPair input, float beta=1.f)
Adds a softmax node to the graph.
bool empty() const
Indicates whether this QuantizationInfo has valid settings or not.
size_t width
Width of the image region or rectangle.
Definition: Size2D.h:92
static NodeID add_fully_connected_layer(Graph &g, NodeParams params, NodeIdxPair input, unsigned int num_outputs, NodeID weights_nid, NodeID bias_nid=EmptyNodeID, const FullyConnectedLayerInfo fc_info=FullyConnectedLayerInfo(), const QuantizationInfo &out_quant_info=QuantizationInfo())
Adds a fully connected layer node to the graph.
ROI Pooling Layer Information class.
Definition: Types.h:1374
constexpr NodeID EmptyNodeID
Constant EdgeID specifying an equivalent of null edge.
Definition: Types.h:71
const INode * node(NodeID id) const
Get node object given its id.
Definition: Graph.cpp:204
Class for specifying the size of an image or rectangle.
Definition: Size2D.h:34
static NodeID add_scale_layer(Graph &g, const NodeParams &params, NodeIdxPair input, ITensorAccessorUPtr mul_accessor=nullptr, ITensorAccessorUPtr add_accessor=nullptr)
Adds a scale layer node to the graph This layer computes a product of the input with a scale (read fr...
ConvolutionMethod
Supported Convolution layer methods.
Definition: Types.h:108
Detection Output layer info.
Definition: Types.h:1092
TensorShape & set(size_t dimension, size_t value, bool apply_dim_correction=true)
Accessor to set the value of one of the dimensions.
Definition: TensorShape.h:78
static TensorDescriptor compute_weights_descriptor(const TensorDescriptor &input_descriptor, unsigned int num_outputs, FullyConnectedLayerInfo fc_info=FullyConnectedLayerInfo(), const QuantizationInfo &weights_quant_info=QuantizationInfo())
Computes weights descriptor.
static NodeID add_const_node(Graph &g, NodeParams params, const TensorDescriptor &desc, ITensorAccessorUPtr accessor=nullptr)
Adds a Const node to the graph.
static NodeID add_flatten_node(Graph &g, NodeParams params, NodeIdxPair input)
Adds a flatten layer node to the graph.
static NodeID add_pooling_node(Graph &g, NodeParams params, NodeIdxPair input, PoolingLayerInfo pool_info)
Adds a pooling layer node to the graph.
DataLayout
[DataLayout enum definition]
Definition: Types.h:117
size_t get_dimension_idx(DataLayout data_layout, const DataLayoutDimension data_layout_dimension)
Get index of a tensor's given dimension depending on its layout.
Definition: Utils.cpp:129
static NodeID add_output_node(Graph &g, NodeParams params, NodeIdxPair input, ITensorAccessorUPtr accessor=nullptr)
Adds an output layer node to the graph.
static NodeID add_depthwise_convolution_node(Graph &g, NodeParams params, NodeIdxPair input, Size2D kernel_spatial_extend, PadStrideInfo conv_info, int depth_multiplier=1, DepthwiseConvolutionMethod method=DepthwiseConvolutionMethod::Default, ITensorAccessorUPtr weights_accessor=nullptr, ITensorAccessorUPtr bias_accessor=nullptr, const QuantizationInfo &quant_info=QuantizationInfo(), const QuantizationInfo &out_quant_info=QuantizationInfo())
Adds a depth-wise convolution layer node to the graph.