blob: 64bda93ff01c39cfa79931e449a999abe7e737e5 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Gian Marco20d78482018-01-11 15:10:58 +00002 * Copyright (c) 2017-2018 ARM Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
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 */
24#include "arm_compute/runtime/CL/functions/CLConvolutionLayer.h"
25
26#include "arm_compute/core/PixelValue.h"
27#include "arm_compute/core/Utils.h"
28#include "arm_compute/core/Validate.h"
Georgios Pinitas78c00902018-01-09 17:33:11 +000029#include "arm_compute/core/utils/misc/ShapeCalculator.h"
30#include "arm_compute/core/utils/quantization/AsymmHelpers.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010031#include "arm_compute/runtime/CL/CLScheduler.h"
32
33#include <cmath>
Georgios Pinitasbaf174e2017-09-08 19:47:30 +010034#include <memory>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010035#include <tuple>
36
37using namespace arm_compute;
Georgios Pinitas78c00902018-01-09 17:33:11 +000038using namespace arm_compute::misc::shape_calculator;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010039
Georgios Pinitasbaf174e2017-09-08 19:47:30 +010040CLConvolutionLayer::CLConvolutionLayer(std::shared_ptr<IMemoryManager> memory_manager)
Isabella Gottardif07d28d2018-02-06 14:52:43 +000041 : _memory_manager(std::move(memory_manager)), _function()
Anthony Barbier6ff3b192017-09-04 18:44:23 +010042{
43}
44
Alex Gilday7da29b62018-03-23 14:16:00 +000045void CLConvolutionLayer::configure(ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info,
46 const Size2D &dilation)
Chunosov5124be52017-11-22 20:42:13 +070047{
Isabella Gottardif07d28d2018-02-06 14:52:43 +000048 ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
Alex Gilday7da29b62018-03-23 14:16:00 +000049 ARM_COMPUTE_ERROR_THROW_ON(CLConvolutionLayer::validate(input->info(), weights->info(), ((biases != nullptr) ? biases->info() : nullptr), output->info(), conv_info, weights_info, dilation));
Isabella Gottardif07d28d2018-02-06 14:52:43 +000050
51 switch(CLConvolutionLayer::get_convolution_method(input->info(), weights->info(), ((biases != nullptr) ? biases->info() : nullptr), output->info(), conv_info,
Alex Gilday7da29b62018-03-23 14:16:00 +000052 weights_info, CLScheduler::get().target(), dilation))
Chunosov5124be52017-11-22 20:42:13 +070053 {
Isabella Gottardif07d28d2018-02-06 14:52:43 +000054 case ConvolutionMethod::DIRECT:
Gian Marco20d78482018-01-11 15:10:58 +000055 {
Isabella Gottardif07d28d2018-02-06 14:52:43 +000056 auto f = arm_compute::support::cpp14::make_unique<CLDirectConvolutionLayer>();
57 f->configure(input, weights, biases, output, conv_info);
58 _function = std::move(f);
59 break;
Gian Marco20d78482018-01-11 15:10:58 +000060 }
Isabella Gottardif07d28d2018-02-06 14:52:43 +000061 case ConvolutionMethod::GEMM:
Gian Marco20d78482018-01-11 15:10:58 +000062 {
Isabella Gottardif07d28d2018-02-06 14:52:43 +000063 auto f = arm_compute::support::cpp14::make_unique<CLGEMMConvolutionLayer>(_memory_manager);
Alex Gilday7da29b62018-03-23 14:16:00 +000064 f->configure(input, weights, biases, output, conv_info, weights_info, dilation);
Isabella Gottardif07d28d2018-02-06 14:52:43 +000065 _function = std::move(f);
66 break;
Gian Marco20d78482018-01-11 15:10:58 +000067 }
Isabella Gottardif07d28d2018-02-06 14:52:43 +000068 default:
69 ARM_COMPUTE_ERROR("Not supported.");
70 break;
Chunosov5124be52017-11-22 20:42:13 +070071 }
72}
73
Isabella Gottardif07d28d2018-02-06 14:52:43 +000074Status CLConvolutionLayer::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
Alex Gilday7da29b62018-03-23 14:16:00 +000075 const WeightsInfo &weights_info, const Size2D &dilation)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010076{
Georgios Pinitas78c00902018-01-09 17:33:11 +000077 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, weights, output);
Chunosov5124be52017-11-22 20:42:13 +070078
Isabella Gottardif07d28d2018-02-06 14:52:43 +000079 //Configure if the parameters match the direct convolution or the gemm-based
80 const GPUTarget gpu_target = CLScheduler::get().target();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010081
Alex Gilday7da29b62018-03-23 14:16:00 +000082 switch(CLConvolutionLayer::get_convolution_method(input, weights, biases, output, conv_info, weights_info, gpu_target, dilation))
Anthony Barbier6ff3b192017-09-04 18:44:23 +010083 {
Isabella Gottardif07d28d2018-02-06 14:52:43 +000084 case ConvolutionMethod::DIRECT:
Chunosov5124be52017-11-22 20:42:13 +070085 {
Isabella Gottardif07d28d2018-02-06 14:52:43 +000086 // Validate direct convolution layer
Isabella Gottardicac4a2e2018-02-19 16:42:22 +000087 CLDirectConvolutionLayer::validate(input, weights, biases, output, conv_info);
Isabella Gottardif07d28d2018-02-06 14:52:43 +000088 break;
Chunosov5124be52017-11-22 20:42:13 +070089 }
Isabella Gottardif07d28d2018-02-06 14:52:43 +000090 case ConvolutionMethod::GEMM:
Chunosov5124be52017-11-22 20:42:13 +070091 {
Isabella Gottardif07d28d2018-02-06 14:52:43 +000092 // Validate gemm-based convolution layer
Alex Gilday7da29b62018-03-23 14:16:00 +000093 CLGEMMConvolutionLayer::validate(input, weights, biases, output, conv_info, weights_info, dilation);
Isabella Gottardif07d28d2018-02-06 14:52:43 +000094 break;
Chunosov5124be52017-11-22 20:42:13 +070095 }
Isabella Gottardif07d28d2018-02-06 14:52:43 +000096 default:
97 ARM_COMPUTE_ERROR("Not supported.");
98 break;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010099 }
100
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000101 return Status{};
102}
Gian Marco Iodice368da832017-07-03 12:33:49 +0100103
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000104ConvolutionMethod CLConvolutionLayer::get_convolution_method(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
Alex Gilday7da29b62018-03-23 14:16:00 +0000105 const WeightsInfo &weights_info, const GPUTarget gpu_target, const Size2D &dilation)
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000106{
107 ARM_COMPUTE_UNUSED(input);
Isabella Gottardicac4a2e2018-02-19 16:42:22 +0000108 ARM_COMPUTE_UNUSED(weights);
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000109 ARM_COMPUTE_UNUSED(biases);
110 ARM_COMPUTE_UNUSED(output);
111 ARM_COMPUTE_UNUSED(conv_info);
112 ARM_COMPUTE_UNUSED(weights_info);
Isabella Gottardicac4a2e2018-02-19 16:42:22 +0000113 ARM_COMPUTE_UNUSED(gpu_target);
Alex Gilday7da29b62018-03-23 14:16:00 +0000114 ARM_COMPUTE_UNUSED(dilation);
Gian Marco Iodice1246b632017-08-16 18:38:32 +0100115
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000116 return ConvolutionMethod::GEMM;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100117}
118
119void CLConvolutionLayer::run()
120{
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000121 _function->run();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100122}