Compute Library
 20.08
GCFunctionsFactory.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 
31 
32 using namespace arm_compute::utils::cast;
33 
34 namespace arm_compute
35 {
36 namespace graph
37 {
38 namespace backends
39 {
40 /** Target specific information structure used to pass information to the layer templates */
41 struct GCTargetInfo
42 {
44  using SrcTensorType = TensorType;
45  static Target TargetType;
46 };
47 
48 Target GCTargetInfo::TargetType = Target::GC;
49 
50 /** Collection of GC convolution functions */
51 struct GCConvolutionLayerFunctions
52 {
53  using GenericConvolutionLayer = GCConvolutionLayer;
54  using GEMMConvolutionLayer = GCConvolutionLayer;
55  using DirectConvolutionLayer = GCDirectConvolutionLayer;
56 };
57 
58 /** Collection of GC depthwise convolution functions */
59 struct GCDepthwiseConvolutionLayerFunctions
60 {
61  using DepthwiseConvolutionLayer3x3 = GCDepthwiseConvolutionLayer3x3;
62 };
63 
64 /** Collection of GC element-wise functions */
65 struct GCEltwiseFunctions
66 {
67  using Addition = GCArithmeticAddition;
68  using Multiplication = GCPixelWiseMultiplication;
69 };
70 
71 namespace detail
72 {
73 template <>
75 {
76  validate_node<GCTargetInfo>(node, 3 /* expected inputs */, 1 /* expected outputs */);
77 
78  // Extract IO and info
79  GCTargetInfo::TensorType *input = get_backing_tensor<GCTargetInfo>(node.input(0));
80  GCTargetInfo::TensorType *weights = get_backing_tensor<GCTargetInfo>(node.input(1));
81  GCTargetInfo::TensorType *biases = get_backing_tensor<GCTargetInfo>(node.input(2));
82  GCTargetInfo::TensorType *output = get_backing_tensor<GCTargetInfo>(node.output(0));
83 
84  if(is_data_type_quantized_asymmetric(input->info()->data_type()))
85  {
86  biases->info()->set_data_type(DataType::S32);
87  }
88 
90  const ConvolutionMethod conv_algorithm = node.convolution_method();
91  const ActivationLayerInfo fused_act = node.fused_activation();
92 
93  // Create and configure function (we assume that functions have been validated before creation)
94  std::shared_ptr<IMemoryManager> mm = get_memory_manager(ctx, GCTargetInfo::TargetType);
95  std::unique_ptr<IFunction> func;
96  std::string func_name;
97 
98  if(conv_algorithm == ConvolutionMethod::Direct)
99  {
100  std::tie(func, func_name) = create_named_function<GCConvolutionLayerFunctions::DirectConvolutionLayer>(
101  std::string("DirectConvolutionLayer"),
102  input, weights, biases, output, conv_info, fused_act);
103  }
104  else
105  {
106  std::tie(func, func_name) = create_named_memory_managed_function<GCConvolutionLayerFunctions::GenericConvolutionLayer>(
107  std::string("ConvolutionLayer"), mm,
108  input, weights, biases, output, conv_info, WeightsInfo(), Size2D(1U, 1U), fused_act);
109  }
110 
111  // Log info
112  ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated "
113  << node.name()
114  << " Type: " << func_name
115  << " Data Type: " << input->info()->data_type()
116  << " Input QuantInfo: " << input->info()->quantization_info()
117  << " Weights QuantInfo: " << weights->info()->quantization_info()
118  << " Input shape: " << input->info()->tensor_shape()
119  << " Weights shape: " << weights->info()->tensor_shape()
120  << " Output shape: " << output->info()->tensor_shape()
121  << (fused_act.enabled() ? " " + to_string(fused_act.activation()) : "")
122  << std::endl);
123  return func;
124 }
125 
126 template <>
128 {
129  validate_node<GCTargetInfo>(node, 3 /* expected inputs */, 1 /* expected outputs */);
130 
131  // Extract IO and info
132  GCTargetInfo::TensorType *input = get_backing_tensor<GCTargetInfo>(node.input(0));
133  GCTargetInfo::TensorType *weights = get_backing_tensor<GCTargetInfo>(node.input(1));
134  GCTargetInfo::TensorType *biases = get_backing_tensor<GCTargetInfo>(node.input(2));
135  GCTargetInfo::TensorType *output = get_backing_tensor<GCTargetInfo>(node.output(0));
136 
137  if(is_data_type_quantized_asymmetric(input->info()->data_type()))
138  {
139  biases->info()->set_data_type(DataType::S32);
140  }
141 
143  const DepthwiseConvolutionMethod dwc_algorithm = node.depthwise_convolution_method();
144  const ActivationLayerInfo fused_act = node.fused_activation();
145  const int depth_multiplier = node.depth_multiplier();
146 
147  // Create and configure function (we assume that functions have been validated before creation)
148  std::unique_ptr<IFunction> func;
149  std::string func_name;
150  if(dwc_algorithm == DepthwiseConvolutionMethod::Optimized3x3)
151  {
152  std::tie(func, func_name) = create_named_function<GCDepthwiseConvolutionLayerFunctions::DepthwiseConvolutionLayer3x3>(
153  std::string("DepthwiseConvolutionLayer3x3"),
154  input, weights, biases, output, conv_info, depth_multiplier, fused_act);
155  }
156  else
157  {
158  ARM_COMPUTE_ERROR("Generic DepthwiseConvolutionLayer is not supported in GLES backend");
159  }
160 
161  // Log info
162  ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated "
163  << node.name()
164  << " Type: " << func_name
165  << " Target " << GCTargetInfo::TargetType
166  << " Data Type: " << input->info()->data_type()
167  << " Input QuantInfo: " << input->info()->quantization_info()
168  << " Weights QuantInfo: " << weights->info()->quantization_info()
169  << " Input shape: " << input->info()->tensor_shape()
170  << " Weights shape: " << weights->info()->tensor_shape()
171  << " Output shape: " << output->info()->tensor_shape()
172  << " Depth multiplier: " << depth_multiplier
173  << (fused_act.enabled() ? " " + to_string(fused_act.activation()) : "")
174  << std::endl);
175  return func;
176 }
177 
178 template <>
180 {
182  "Creating GC EltwiseLayer node with ID : " << node.id() << " and Name: " << node.name() << std::endl);
183  ARM_COMPUTE_ERROR_ON(node.num_inputs() != 2);
184  ARM_COMPUTE_ERROR_ON(node.num_outputs() != 1);
185 
186  // Extract IO and info
187  GCTargetInfo::TensorType *input1 = get_backing_tensor<GCTargetInfo>(node.input(0));
188  GCTargetInfo::TensorType *input2 = get_backing_tensor<GCTargetInfo>(node.input(1));
189  GCTargetInfo::TensorType *output = get_backing_tensor<GCTargetInfo>(node.output(0));
190  const EltwiseOperation eltwise_op = node.eltwise_operation();
191  const ConvertPolicy convert_policy = node.convert_policy();
192  ARM_COMPUTE_ERROR_ON(input1 == nullptr);
193  ARM_COMPUTE_ERROR_ON(input2 == nullptr);
194  ARM_COMPUTE_ERROR_ON(output == nullptr);
195 
196  std::unique_ptr<IFunction> func = nullptr;
197  std::string func_name;
198  if(eltwise_op == EltwiseOperation::Add)
199  {
200  std::tie(func, func_name) = create_named_function<GCEltwiseFunctions::Addition>(
201  std::string("GCArithmeticAddition"),
202  input1, input2, output, convert_policy);
203  }
204  else if(eltwise_op == EltwiseOperation::Sub)
205  {
206  ARM_COMPUTE_ERROR("Arithmetic subtraction is not supported in GLES backend");
207  }
208  else if(eltwise_op == EltwiseOperation::Mul)
209  {
210  std::tie(func, func_name) = create_named_function<GCEltwiseFunctions::Multiplication>(
211  std::string("PixelWiseMultiplication"),
212  input1, input2, output, 1.f);
213  }
214  else
215  {
216  ARM_COMPUTE_ERROR("Unsupported element-wise operation!");
217  }
218 
219  // Log info
220  ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated "
221  << node.name()
222  << " Type: " << node.type()
223  << " Target: " << GCTargetInfo::TargetType
224  << " Operation: " << func_name
225  << " Data Type: " << input1->info()->data_type()
226  << " Shape: " << input1->info()->tensor_shape()
227  << std::endl);
228 
229  return func;
230 }
231 } //namespace detail
232 
233 std::unique_ptr<IFunction> GCFunctionFactory::create(INode *node, GraphContext &ctx)
234 {
235  if(node == nullptr)
236  {
237  return nullptr;
238  }
239 
240  NodeType type = node->type();
241  switch(type)
242  {
243  case NodeType::ActivationLayer:
244  return detail::create_activation_layer<GCActivationLayer, GCTargetInfo>(*polymorphic_downcast<ActivationLayerNode *>(node));
245  case NodeType::BatchNormalizationLayer:
246  return detail::create_batch_normalization_layer<GCBatchNormalizationLayer, GCTargetInfo>(*polymorphic_downcast<BatchNormalizationLayerNode *>(node));
247  case NodeType::ConvolutionLayer:
248  return detail::create_convolution_layer<GCConvolutionLayerFunctions, GCTargetInfo>(*polymorphic_downcast<ConvolutionLayerNode *>(node), ctx);
249  case NodeType::ConcatenateLayer:
250  return detail::create_concatenate_layer<GCConcatenateLayer, GCTargetInfo>(*polymorphic_downcast<ConcatenateLayerNode *>(node));
251  case NodeType::DepthwiseConvolutionLayer:
252  return detail::create_depthwise_convolution_layer<GCDepthwiseConvolutionLayerFunctions, GCTargetInfo>(*polymorphic_downcast<DepthwiseConvolutionLayerNode *>(node));
253  case NodeType::EltwiseLayer:
254  return detail::create_eltwise_layer<GCEltwiseFunctions, GCTargetInfo>(*polymorphic_downcast<EltwiseLayerNode *>(node));
255  case NodeType::FullyConnectedLayer:
256  return detail::create_fully_connected_layer<GCFullyConnectedLayer, GCTargetInfo>(*polymorphic_downcast<FullyConnectedLayerNode *>(node), ctx);
257  case NodeType::NormalizationLayer:
258  return detail::create_normalization_layer<GCNormalizationLayer, GCTargetInfo>(*polymorphic_downcast<NormalizationLayerNode *>(node), ctx);
259  case NodeType::NormalizePlanarYUVLayer:
260  return detail::create_normalize_planar_yuv_layer<GCNormalizePlanarYUVLayer, GCTargetInfo>(*polymorphic_downcast<NormalizePlanarYUVLayerNode *>(node));
261  case NodeType::PoolingLayer:
262  return detail::create_pooling_layer<GCPoolingLayer, GCTargetInfo>(*polymorphic_downcast<PoolingLayerNode *>(node));
263  case NodeType::PrintLayer:
264  return detail::create_print_layer<GCTargetInfo>(*polymorphic_downcast<PrintLayerNode *>(node));
265  case NodeType::ResizeLayer:
266  return detail::create_resize_layer<GCScale, GCTargetInfo>(*polymorphic_downcast<ResizeLayerNode *>(node));
267  case NodeType::SoftmaxLayer:
268  return detail::create_softmax_layer<GCSoftmaxLayer, GCTargetInfo>(*polymorphic_downcast<SoftmaxLayerNode *>(node), ctx);
269  default:
270  return nullptr;
271  }
272 }
273 } // namespace backends
274 } // namespace graph
275 } // namespace arm_compute
std::string name() const
Returns node's name.
Definition: INode.cpp:107
NodeType type() const override
Returns node's type.
EltwiseOperation
Supported Element-wise operations.
Definition: Types.h:102
bool enabled() const
Check if initialised.
Definition: Types.h:1567
ActivationLayerInfo fused_activation() const
Returns fused activation.
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
TensorType
Memory type.
Definition: Types.h:38
size_t num_outputs() const
Returns number of outputs of the node.
Definition: INode.cpp:183
ActivationLayerInfo fused_activation() const
Returns fused activation.
#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
Interface for GLES Compute tensor.
Definition: IGCTensor.h:35
DepthwiseConvolutionMethod depthwise_convolution_method() const
Depthwise convolution layer method accessor.
EltwiseOperation eltwise_operation() const
Eltwise operation accessor.
Activation Layer Information class.
Definition: Types.h:1517
#define ARM_COMPUTE_LOG_GRAPH_INFO(x)
Definition: Logger.h:54
Copyright (c) 2017-2020 Arm Limited.
ITensorInfo * info() const override
Interface to be implemented by the child class to return the tensor's metadata.
Definition: Tensor.cpp:33
Convolution Layer Weights Information class.
Definition: Types.h:1694
1 channel, 1 S32 per channel
Node interface.
Definition: INode.h:45
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
Tensor * output(size_t idx) const
Returns the tensor of a given output of the node.
Definition: INode.cpp:158
DepthwiseConvolutionMethod
Supported Depthwise Convolution layer methods.
Definition: Types.h:125
PadStrideInfo convolution_info() const
Convolution metadata accessor.
NodeID id() const
Returns node's ID.
Definition: INode.cpp:102
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor's metadata.
NodeType
Supported nodes.
Definition: Types.h:140
PadStrideInfo convolution_info() const
Convolution metadata accessor.
Padding and stride information class.
Definition: Types.h:689
std::unique_ptr< IFunction > create_depthwise_convolution_layer< GCDepthwiseConvolutionLayerFunctions, GCTargetInfo >(DepthwiseConvolutionLayerNode &node)
virtual ITensorInfo & set_data_type(DataType data_type)=0
Set the data type to the specified value.
virtual QuantizationInfo quantization_info() const =0
Get the quantization settings (scale and offset) of the tensor.
bool is_data_type_quantized_asymmetric(DataType dt)
Check if a given data type is of asymmetric quantized type.
Definition: Utils.h:1143
ConvolutionMethod convolution_method() const
Convolution layer method accessor.
Class for specifying the size of an image or rectangle.
Definition: Size2D.h:34
std::string to_string(const ICLTensor &arg)
std::shared_ptr< IMemoryManager > get_memory_manager(GraphContext &ctx, Target target)
Returns the memory manager for a given target.
Definition: Utils.h:89
#define ARM_COMPUTE_LOG_GRAPH_VERBOSE(x)
Definition: Logger.h:50
ConvolutionMethod
Supported Convolution layer methods.
Definition: Types.h:116
size_t num_inputs() const
Returns number of inputs of the node.
Definition: INode.cpp:178
ConvertPolicy convert_policy() const
Convert policy accessor.
std::unique_ptr< IFunction > create_eltwise_layer< GCEltwiseFunctions, GCTargetInfo >(EltwiseLayerNode &node)
ActivationFunction activation() const
Get the type of activation function.
Definition: Types.h:1552
virtual NodeType type() const =0
Returns node's type.
Tensor * input(size_t idx) const
Returns the tensor of a given input of the node.
Definition: INode.cpp:150
ConvertPolicy
Policy to handle overflow.
Definition: Types.h:362
std::unique_ptr< IFunction > create_convolution_layer< GCConvolutionLayerFunctions, GCTargetInfo >(ConvolutionLayerNode &node, GraphContext &ctx)