blob: 5b329c04bea0d18433eb1ec19ae0c336e8db4a2d [file] [log] [blame]
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001/*
2 * Copyright (c) 2018 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 */
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010024#include "arm_compute/graph/backends/CL/CLFunctionFactory.h"
Georgios Pinitasd8734b52017-12-22 15:27:52 +000025
26#include "arm_compute/core/utils/misc/Cast.h"
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010027#include "arm_compute/graph/Graph.h"
Georgios Pinitasda2491f2018-06-01 17:49:09 +010028#include "arm_compute/graph/backends/FunctionHelpers.h"
Georgios Pinitasd8734b52017-12-22 15:27:52 +000029#include "arm_compute/runtime/CL/CLFunctions.h"
Isabella Gottardi7234ed82018-11-27 08:51:10 +000030#include "arm_compute/runtime/CPP/CPPFunctions.h"
Georgios Pinitasd8734b52017-12-22 15:27:52 +000031
Georgios Pinitasd8734b52017-12-22 15:27:52 +000032using namespace arm_compute::utils::cast;
33
34namespace arm_compute
35{
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010036namespace graph
Georgios Pinitasd8734b52017-12-22 15:27:52 +000037{
38namespace backends
39{
Georgios Pinitasda2491f2018-06-01 17:49:09 +010040/** Target specific information structure used to pass information to the layer templates */
41struct CLTargetInfo
Georgios Pinitasd8734b52017-12-22 15:27:52 +000042{
Georgios Pinitasda2491f2018-06-01 17:49:09 +010043 using TensorType = arm_compute::ICLTensor;
44 static Target TargetType;
45};
46
47Target CLTargetInfo::TargetType = Target::CL;
48
49/** Collection of CL convolution functions */
50struct CLConvolutionLayerFunctions
Georgios Pinitasd8734b52017-12-22 15:27:52 +000051{
Georgios Pinitasda2491f2018-06-01 17:49:09 +010052 using GenericConvolutionLayer = CLConvolutionLayer;
53 using GEMMConvolutionLayer = CLGEMMConvolutionLayer;
54 using DirectConvolutionLayer = CLDirectConvolutionLayer;
55 using WinogradConvolutionLayer = CLWinogradConvolutionLayer;
56};
Georgios Pinitasd8734b52017-12-22 15:27:52 +000057
Georgios Pinitasda2491f2018-06-01 17:49:09 +010058/** Collection of CL depthwise convolution functions */
59struct CLDepthwiseConvolutionLayerFunctions
Georgios Pinitasd8734b52017-12-22 15:27:52 +000060{
Georgios Pinitasda2491f2018-06-01 17:49:09 +010061 using GenericDepthwiseConvolutionLayer = CLDepthwiseConvolutionLayer;
62 using DepthwiseConvolutionLayer3x3 = CLDepthwiseConvolutionLayer3x3;
63};
Georgios Pinitasd8734b52017-12-22 15:27:52 +000064
Georgios Pinitasda2491f2018-06-01 17:49:09 +010065/** Collection of CL element-wise functions */
66struct CLEltwiseFunctions
Georgios Pinitasd8734b52017-12-22 15:27:52 +000067{
Georgios Pinitasda2491f2018-06-01 17:49:09 +010068 using Addition = CLArithmeticAddition;
69 using Subtraction = CLArithmeticSubtraction;
70 using Multiplication = CLPixelWiseMultiplication;
71};
Isabella Gottardi7234ed82018-11-27 08:51:10 +000072// TODO (isagot01): Remove once we support heterogeneous scheduling at function level
73/** Wrapper for the CPP Function in the OpenCL backend **/
74class CPPWrapperFunction : public IFunction
75{
76public:
77 /* Default constructor */
78 CPPWrapperFunction()
79 : _tensors(), _func(nullptr)
80 {
81 }
82
83 void run() override
84 {
85 for(auto &tensor : _tensors)
86 {
87 tensor->map(CLScheduler::get().queue());
88 }
89 _func->run();
90
91 for(auto &tensor : _tensors)
92 {
93 tensor->unmap(CLScheduler::get().queue());
94 }
95 }
96
97 void register_tensor(ICLTensor *tensor)
98 {
99 _tensors.push_back(tensor);
100 }
101
102 void register_function(std::unique_ptr<IFunction> function)
103 {
104 _func = std::move(function);
105 }
106
107private:
108 std::vector<arm_compute::ICLTensor *> _tensors;
109 std::unique_ptr<IFunction> _func;
110};
111
112namespace detail
113{
114// Specialized functions
115template <>
116std::unique_ptr<IFunction> create_detection_output_layer<CPPDetectionOutputLayer, CLTargetInfo>(DetectionOutputLayerNode &node)
117{
118 validate_node<CLTargetInfo>(node, 3 /* expected inputs */, 1 /* expected outputs */);
119
120 // Extract IO and info
121 CLTargetInfo::TensorType *input0 = get_backing_tensor<CLTargetInfo>(node.input(0));
122 CLTargetInfo::TensorType *input1 = get_backing_tensor<CLTargetInfo>(node.input(1));
123 CLTargetInfo::TensorType *input2 = get_backing_tensor<CLTargetInfo>(node.input(2));
124 CLTargetInfo::TensorType *output = get_backing_tensor<CLTargetInfo>(node.output(0));
125 const DetectionOutputLayerInfo detect_info = node.detection_output_info();
126
127 ARM_COMPUTE_ERROR_ON(input0 == nullptr);
128 ARM_COMPUTE_ERROR_ON(input1 == nullptr);
129 ARM_COMPUTE_ERROR_ON(input2 == nullptr);
130 ARM_COMPUTE_ERROR_ON(output == nullptr);
131
132 // Create and configure function
133 auto func = support::cpp14::make_unique<CPPDetectionOutputLayer>();
134 func->configure(input0, input1, input2, output, detect_info);
135
136 // Log info
137 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated "
138 << node.name()
139 << " Type: " << node.type()
140 << " Target: " << CLTargetInfo::TargetType
141 << " Data Type: " << input0->info()->data_type()
142 << " Input0 shape: " << input0->info()->tensor_shape()
143 << " Input1 shape: " << input1->info()->tensor_shape()
144 << " Input2 shape: " << input2->info()->tensor_shape()
145 << " Output shape: " << output->info()->tensor_shape()
146 << " DetectionOutputLayer info: " << detect_info
147 << std::endl);
148
149 auto wrap_function = support::cpp14::make_unique<CPPWrapperFunction>();
150 ;
151 wrap_function->register_function(std::move(func));
152 wrap_function->register_tensor(input0);
153 wrap_function->register_tensor(input1);
154 wrap_function->register_tensor(input2);
155 wrap_function->register_tensor(output);
156
157 return std::move(wrap_function);
158}
159} // namespace detail
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000160
161std::unique_ptr<IFunction> CLFunctionFactory::create(INode *node, GraphContext &ctx)
162{
163 if(node == nullptr)
164 {
165 return nullptr;
166 }
167
168 NodeType type = node->type();
169 switch(type)
170 {
171 case NodeType::ActivationLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100172 return detail::create_activation_layer<CLActivationLayer, CLTargetInfo>(*polymorphic_downcast<ActivationLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000173 case NodeType::BatchNormalizationLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100174 return detail::create_batch_normalization_layer<CLBatchNormalizationLayer, CLTargetInfo>(*polymorphic_downcast<BatchNormalizationLayerNode *>(node));
Manuel Bottinid2048ce2018-10-23 17:00:42 +0100175 case NodeType::BoundingBoxTransformLayer:
176 return detail::create_bounding_box_transform_layer<CLBoundingBoxTransform, CLTargetInfo>(*polymorphic_downcast<BoundingBoxTransformLayerNode *>(node));
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100177 case NodeType::ChannelShuffleLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100178 return detail::create_channel_shuffle_layer<CLChannelShuffleLayer, CLTargetInfo>(*polymorphic_downcast<ChannelShuffleLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000179 case NodeType::ConvolutionLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100180 return detail::create_convolution_layer<CLConvolutionLayerFunctions, CLTargetInfo>(*polymorphic_downcast<ConvolutionLayerNode *>(node), ctx);
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100181 case NodeType::DeconvolutionLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100182 return detail::create_deconvolution_layer<CLDeconvolutionLayer, CLTargetInfo>(*polymorphic_downcast<DeconvolutionLayerNode *>(node), ctx);
Georgios Pinitase2220552018-07-20 13:23:44 +0100183 case NodeType::ConcatenateLayer:
184 return detail::create_concatenate_layer<CLConcatenateLayer, CLTargetInfo>(*polymorphic_downcast<ConcatenateLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000185 case NodeType::DepthwiseConvolutionLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100186 return detail::create_depthwise_convolution_layer<CLDepthwiseConvolutionLayerFunctions, CLTargetInfo>(*polymorphic_downcast<DepthwiseConvolutionLayerNode *>(node));
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000187 case NodeType::DetectionOutputLayer:
188 return detail::create_detection_output_layer<CPPDetectionOutputLayer, CLTargetInfo>(*polymorphic_downcast<DetectionOutputLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000189 case NodeType::EltwiseLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100190 return detail::create_eltwise_layer<CLEltwiseFunctions, CLTargetInfo>(*polymorphic_downcast<EltwiseLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000191 case NodeType::FlattenLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100192 return detail::create_flatten_layer<CLFlattenLayer, CLTargetInfo>(*polymorphic_downcast<FlattenLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000193 case NodeType::FullyConnectedLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100194 return detail::create_fully_connected_layer<CLFullyConnectedLayer, CLTargetInfo>(*polymorphic_downcast<FullyConnectedLayerNode *>(node), ctx);
Michele Di Giorgio47e6fed2018-11-13 12:04:25 +0000195 case NodeType::GenerateProposalsLayer:
196 return detail::create_generate_proposals_layer<CLGenerateProposalsLayer, CLTargetInfo>(*polymorphic_downcast<GenerateProposalsLayerNode *>(node), ctx);
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000197 case NodeType::NormalizationLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100198 return detail::create_normalization_layer<CLNormalizationLayer, CLTargetInfo>(*polymorphic_downcast<NormalizationLayerNode *>(node), ctx);
Michele Di Giorgio555d1102018-09-12 13:51:59 +0100199 case NodeType::NormalizePlanarYUVLayer:
200 return detail::create_normalize_planar_yuv_layer<CLNormalizePlanarYUVLayer, CLTargetInfo>(*polymorphic_downcast<NormalizePlanarYUVLayerNode *>(node));
Michele Di Giorgio4bb17332018-09-26 13:56:51 +0100201 case NodeType::PadLayer:
202 return detail::create_pad_layer<CLPadLayer, CLTargetInfo>(*polymorphic_downcast<PadLayerNode *>(node));
Georgios Pinitas57c48242018-08-02 13:41:49 +0100203 case NodeType::PermuteLayer:
204 return detail::create_permute_layer<CLPermute, CLTargetInfo>(*polymorphic_downcast<PermuteLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000205 case NodeType::PoolingLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100206 return detail::create_pooling_layer<CLPoolingLayer, CLTargetInfo>(*polymorphic_downcast<PoolingLayerNode *>(node));
Pablo Tello32521432018-11-15 14:43:10 +0000207 case NodeType::PriorBoxLayer:
208 return detail::create_priorbox_layer<CLPriorBoxLayer, CLTargetInfo>(*polymorphic_downcast<PriorBoxLayerNode *>(node));
Gian Marco Iodice23e24792018-09-07 15:32:14 +0100209 case NodeType::ReorgLayer:
210 return detail::create_reorg_layer<CLReorgLayer, CLTargetInfo>(*polymorphic_downcast<ReorgLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000211 case NodeType::ReshapeLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100212 return detail::create_reshape_layer<CLReshapeLayer, CLTargetInfo>(*polymorphic_downcast<ReshapeLayerNode *>(node));
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100213 case NodeType::ResizeLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100214 return detail::create_resize_layer<CLScale, CLTargetInfo>(*polymorphic_downcast<ResizeLayerNode *>(node));
Manuel Bottini3f9d4d72018-10-19 14:04:42 +0100215 case NodeType::ROIAlignLayer:
216 return detail::create_roi_align_layer<CLROIAlignLayer, CLTargetInfo>(*polymorphic_downcast<ROIAlignLayerNode *>(node));
Michele Di Giorgioc30b6682018-09-12 17:44:08 +0100217 case NodeType::SliceLayer:
218 return detail::create_slice_layer<CLSlice, CLTargetInfo>(*polymorphic_downcast<SliceLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000219 case NodeType::SoftmaxLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100220 return detail::create_softmax_layer<CLSoftmaxLayer, CLTargetInfo>(*polymorphic_downcast<SoftmaxLayerNode *>(node), ctx);
Michalis Spyrou4e1c3f32018-09-20 17:14:03 +0100221 case NodeType::UpsampleLayer:
222 return detail::create_upsample_layer<CLUpsampleLayer, CLTargetInfo>(*polymorphic_downcast<UpsampleLayerNode *>(node), ctx);
Michalis Spyrou96f67692018-09-13 11:39:28 +0100223 case NodeType::YOLOLayer:
224 return detail::create_yolo_layer<CLYOLOLayer, CLTargetInfo>(*polymorphic_downcast<YOLOLayerNode *>(node), ctx);
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000225 default:
226 return nullptr;
227 }
228}
229} // namespace backends
Georgios Pinitasd9eb2752018-04-03 13:44:29 +0100230} // namespace graph
Michele Di Giorgio555d1102018-09-12 13:51:59 +0100231} // namespace arm_compute