aboutsummaryrefslogtreecommitdiff
path: root/arm_compute/core/NEON/kernels/NEWinogradConvolutionLayerKernel.h
diff options
context:
space:
mode:
authorPablo Tello <pablo.tello@arm.com>2019-03-27 09:28:32 +0000
committerGeorgios Pinitas <georgios.pinitas@arm.com>2019-04-16 11:31:40 +0000
commit8f43d745b170aefca269a087fc045d8af3813c33 (patch)
tree08df4a26c3fab575eb9bdf061be89d2a71fb3581 /arm_compute/core/NEON/kernels/NEWinogradConvolutionLayerKernel.h
parent9e4824c909b14dbaf7106e9527b0ffa22ef09bdc (diff)
downloadComputeLibrary-8f43d745b170aefca269a087fc045d8af3813c33.tar.gz
COMPMID-2063: New Winograd implementation
Refactoring of winograd code reducing the size of the binaries about 8X. Change-Id: If8845bda324573e1a5cf436f354ac8603e88a92e Signed-off-by: Pablo Tello <pablo.tello@arm.com> Reviewed-on: https://review.mlplatform.org/c/959 Comments-Addressed: Arm Jenkins <bsgcomp@arm.com> Tested-by: Anthony Barbier <Anthony.barbier@arm.com> Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com>
Diffstat (limited to 'arm_compute/core/NEON/kernels/NEWinogradConvolutionLayerKernel.h')
-rw-r--r--arm_compute/core/NEON/kernels/NEWinogradConvolutionLayerKernel.h183
1 files changed, 123 insertions, 60 deletions
diff --git a/arm_compute/core/NEON/kernels/NEWinogradConvolutionLayerKernel.h b/arm_compute/core/NEON/kernels/NEWinogradConvolutionLayerKernel.h
index 96580053dd..f6b189cb1c 100644
--- a/arm_compute/core/NEON/kernels/NEWinogradConvolutionLayerKernel.h
+++ b/arm_compute/core/NEON/kernels/NEWinogradConvolutionLayerKernel.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -27,8 +27,7 @@
#include "arm_compute/core/NEON/INEKernel.h"
#include "arm_compute/core/NEON/kernels/convolution/common/convolution.hpp"
#include "arm_compute/core/NEON/kernels/convolution/common/tensor.hpp"
-#include "arm_compute/core/NEON/kernels/convolution/winograd/batched_blocked_gemm.hpp"
-#include "arm_compute/core/NEON/kernels/convolution/winograd/winograd_gemm.hpp"
+#include "arm_compute/core/NEON/kernels/convolution/winograd/winograd_layer.hpp"
namespace arm_compute
{
@@ -39,6 +38,17 @@ template <typename T>
class INEWinogradLayerTransformInputKernel : public INEKernel
{
public:
+ /** Get the working space required to perform the transformation.
+ *
+ * Note, the working space is only required when performing the
+ * transformation - hence it can be reused whenever the transformation is
+ * not running.
+ *
+ * @param num_threads The greatest number of threads that will be used to execute the transform.
+ * @return Size of working space required in bytes.
+ */
+ virtual unsigned int get_working_space_size(unsigned int num_threads) const = 0;
+
/** Determine how much memory (in units of TIn) to allocate for the
* transformed input.
*
@@ -72,9 +82,10 @@ public:
* @param[in] padding Padding type.
* @param[out] output Base of output matrices.
* @param[in] matrix_stride Stride between output matrices.
+ * @param[in] workspace Tensor to be used as the working space during the computation.
*/
virtual void configure(const ITensor *input_nhwc, const int num_batches, const int num_rows, const int num_cols, const int num_channels,
- const PaddingType padding, ITensor *output, const int matrix_stride) = 0;
+ const PaddingType padding, ITensor *output, const int matrix_stride, ITensor *workspace) = 0;
/** Destructor */
virtual ~INEWinogradLayerTransformInputKernel()
@@ -116,6 +127,18 @@ public:
int num_cols,
bool same_padding) const override;
+ /** Get the working space required to perform the transformation.
+ *
+ * Note, the working space is only required when performing the
+ * transformation - hence it can be reused whenever the transformation is
+ * not running.
+ *
+ * @param[in] num_threads The greatest number of threads that will be used to execute the transform.
+ *
+ * @return Size of working space required in bytes.
+ */
+ unsigned int get_working_space_size(unsigned int num_threads) const override;
+
/** Gets the stride between matrices in the input worspace
*
* @param[in] kernel_shape The shape of the weights tensor.
@@ -144,6 +167,7 @@ public:
* @param[in] padding Padding type.
* @param[out] output Base of output matrices.
* @param[in] matrix_stride Stride between output matrices.
+ * @param[in] workspace Tensor to be used as the working space during the computation.
*/
void configure(
const ITensor *input_nhwc,
@@ -153,13 +177,14 @@ public:
const int num_channels,
const PaddingType padding,
ITensor *output,
- const int matrix_stride) override;
+ const int matrix_stride,
+ ITensor *workspace) override;
// Inherited methods overridden:
void run(const Window &window, const ThreadInfo &info) override;
/** Winograd base kernel */
- using WinogradBase = winograd::WinogradGEMM<OutputTileRows, OutputTileCols, KernelRows, KernelCols>;
+ using WinogradBase = winograd::WinogradGEMM<OutputTileRows, OutputTileCols, KernelRows, KernelCols, winograd::WinogradRoots::Integers>;
/** Winograd convolution kernel */
using WinogradConv = typename WinogradBase::template Convolution<T, T>;
@@ -174,15 +199,22 @@ public:
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const WinogradInfo &winograd_info);
private:
- using InputTransform = typename WinogradBase::template InputTransform<T>;
- const ITensor *_input_nhwc;
- int _num_batches; /**< Number of batches in input tensor. */
- int _num_rows; /**< Number of rows in input tensor. */
- int _num_cols; /**< Number of columns in input tensor. */
- int _num_channels; /**< Number of channels in input tensor. */
- PaddingType _padding; /**< Padding type. */
- ITensor *_output; /**< Base of output matrices. */
- int _matrix_stride; /**< Stride between output matrices. */
+ using InputTransform = typename WinogradBase::template InputTransform<T, T>;
+
+ std::unique_ptr<InputTransform> _transform{ nullptr };
+ const ITensor *_input_nhwc;
+ int _num_batches; /**< Number of batches in input tensor. */
+ int _num_rows; /**< Number of rows in input tensor. */
+ int _num_cols; /**< Number of columns in input tensor. */
+ int _num_channels; /**< Number of channels in input tensor. */
+ PaddingType _padding; /**< Padding type. */
+ ITensor *_output; /**< Base of output matrices. */
+ int _matrix_stride; /**< Stride between output matrices. */
+ int _padding_top; /**< Padding to apply to the top of the image. */
+ int _padding_left; /**< Padding to apply to the left of the image. */
+ int _padding_right; /**< Padding to apply to the right of the image. */
+ int _padding_bottom; /**< Padding to apply to the bottom of the image. */
+ ITensor *_workspace;
};
/** Interface for the NEON kernel to perform Winograd output transform. */
@@ -190,6 +222,18 @@ template <typename T>
class INEWinogradLayerTransformOutputKernel : public INEKernel
{
public:
+ /** Get the working space required to perform the transformation.
+ *
+ * Note, the working space is only required when performing the
+ * transformation - hence it can be reused whenever the transformation is
+ * not running.
+ *
+ * @param[in] num_threads The greatest number of threads that will be used to execute the transform.
+ *
+ * @return Size of working space required in bytes.
+ */
+ virtual unsigned int get_working_space_size(unsigned int num_threads) const = 0;
+
/** Determine how much memory (in units of TOut) to allocate for the
* (Winograd domain) output.
*
@@ -225,24 +269,26 @@ public:
/** Configure the output transform kernel.
*
- * @param[in] biases Pointer to the biases tensor.
- * @param[in] output_workingspace Pointer to working space for the output tensor in the Winograd domain.
- * @param[in] matrix_stride Output matrix stride, can be computed with winograd::WinogradGEMM<2, 2, 3, 3>::Convolution<float, float>::get_output_matrix_stride()
- * @param[out] output_nhwc Pointer to a tensor in NHWC data layout ordered output tensor, in the spatial domain.
- * @param[in] num_batches Number of batches in the input tensor.
- * @param[in] num_rows Number of rows in output tensor.
- * @param[in] num_cols Number of columns in output tensor.
- * @param[in] num_channels Number of feature maps in the output tensor.
+ * @param[in] biases Pointer to the biases tensor.
+ * @param[in] transformed_output Pointer to working space for the output tensor in the Winograd domain.
+ * @param[in] matrix_stride Output matrix stride, can be computed with winograd::WinogradGEMM<2, 2, 3, 3>::Convolution<float, float>::get_output_matrix_stride()
+ * @param[out] output_nhwc Pointer to a tensor in NHWC data layout ordered output tensor, in the spatial domain.
+ * @param[in] num_batches Number of batches in the input tensor.
+ * @param[in] num_rows Number of rows in output tensor.
+ * @param[in] num_cols Number of columns in output tensor.
+ * @param[in] num_channels Number of feature maps in the output tensor.
+ * @param[in] workspace Tensor to be used as the working space during the computation.
*/
virtual void configure(
const ITensor *biases,
- const ITensor *output_workingspace,
+ const ITensor *transformed_output,
const int matrix_stride,
ITensor *output_nhwc,
const int num_batches,
const int num_rows,
const int num_cols,
- const int num_channels) = 0;
+ const int num_channels,
+ ITensor *workspace) = 0;
virtual ~INEWinogradLayerTransformOutputKernel()
{
@@ -305,54 +351,70 @@ public:
*/
Tensor4DShape get_output_shape(const KernelShape &kernel_shape, const Tensor4DShape &in_shape, const PaddingType padding) const override;
+ /** Get the working space required to perform the transformation.
+ *
+ * Note, the working space is only required when performing the
+ * transformation - hence it can be reused whenever the transformation is
+ * not running.
+ *
+ * @param[in] num_threads The greatest number of threads that will be used to execute the transform.
+ *
+ * @return Size of working space required in bytes.
+ */
+ unsigned int get_working_space_size(unsigned int num_threads) const override;
+
/** Configure the output transform kernel.
*
- * @param[in] biases Pointer to the biases tensor.
- * @param[in] output_workingspace Pointer to working space for the output tensor in the Winograd domain.
- * @param[in] matrix_stride Output matrix stride, can be computed with winograd::WinogradGEMM<2, 2, 3, 3>::Convolution<float, float>::get_output_matrix_stride()
- * @param[out] output_nhwc Pointer to a tensor with NHWC data layout, in the spatial domain.
- * @param[in] num_batches Number of batches in the input tensor.
- * @param[in] num_rows Number of rows in output tensor.
- * @param[in] num_cols Number of columns in output tensor.
- * @param[in] num_channels Number of feature maps in the output tensor.
+ * @param[in] biases Pointer to the biases tensor.
+ * @param[in] transformed_output Pointer to working space for the output tensor in the Winograd domain.
+ * @param[in] matrix_stride Output matrix stride, can be computed with winograd::WinogradGEMM<2, 2, 3, 3>::Convolution<float, float>::get_output_matrix_stride()
+ * @param[out] output_nhwc Pointer to a tensor with NHWC data layout, in the spatial domain.
+ * @param[in] num_batches Number of batches in the input tensor.
+ * @param[in] num_rows Number of rows in output tensor.
+ * @param[in] num_cols Number of columns in output tensor.
+ * @param[in] num_channels Number of feature maps in the output tensor.
+ * @param[in] workspace Tensor to be used as the working space during the computation.
*/
void configure(
const ITensor *biases,
- const ITensor *output_workingspace,
+ const ITensor *transformed_output,
const int matrix_stride,
ITensor *output_nhwc,
const int num_batches,
const int num_rows,
const int num_cols,
- const int num_channels) override;
+ const int num_channels,
+ ITensor *workspace) override;
void run(const Window &window, const ThreadInfo &info) override;
/** Static function to check if given info will lead to a valid configuration of @ref NEWinogradLayerTransformOutputKernel
*
- * @param[in] input Source tensor with shape [C, N, 16, batches] or [C, N, 36, batches]. Data types supported: F32.
- * @param[in] bias Biases tensor. Shared biases supported. Biases are 1D tensor with dimensions [OFM]. It can be a nullptr. Data type supported: as @p input
- * @param[out] output Destination tensor with shape [output_convolved_dims.width, output_convolved_dims.height, C, batches]. Data type supported: same as @p input
- * @param[in] winograd_info Contains Winograd's information described in @ref WinogradInfo
+ * @param[in] input Source tensor info with shape [C, N, 16, batches] or [C, N, 36, batches]. Data types supported: F32.
+ * @param[in] bias Biases tensor info. Shared biases supported. Biases are 1D tensor with dimensions [OFM]. It can be a nullptr. Data type supported: as @p input
+ * @param[in] output Destination tensor info with shape [output_convolved_dims.width, output_convolved_dims.height, C, batches]. Data type supported: same as @p input
+ * @param[in] winograd_info Contains Winograd's information described in @ref WinogradInfo
*
* @return a status
*/
static Status validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const WinogradInfo &winograd_info);
private:
- using WinogradBase = winograd::WinogradGEMM<OutputTileRows, OutputTileCols, KernelRows, KernelCols>;
+ using WinogradBase = winograd::WinogradGEMM<OutputTileRows, OutputTileCols, KernelRows, KernelCols, winograd::WinogradRoots::Integers>;
using WinogradConv = typename WinogradBase::template Convolution<T, T>;
- using OutputTransform = typename WinogradBase::template OutputTransform<T>;
-
- const ITensor *_biases;
- const ITensor *_output_workspace;
- int _matrix_stride;
- int _matrix_row_stride;
- ITensor *_output_nhwc;
- int _num_batches;
- int _num_rows;
- int _num_cols;
- int _num_channels;
+ using OutputTransform = typename WinogradBase::template OutputTransform<T, T>;
+
+ std::unique_ptr<OutputTransform> _transform{ nullptr };
+ const ITensor *_biases;
+ const ITensor *_transformed_output;
+ ITensor *_workspace;
+ int _matrix_stride;
+ int _matrix_row_stride;
+ ITensor *_output_nhwc;
+ int _num_batches;
+ int _num_rows;
+ int _num_cols;
+ int _num_channels;
};
/** Interface for the NEON kernel to perform Winograd weights transform. */
@@ -482,15 +544,16 @@ public:
bool is_parallelisable() const override;
private:
- using WinogradBase = winograd::WinogradGEMM<OutputTileRows, OutputTileCols, KernelRows, KernelCols>;
+ using WinogradBase = winograd::WinogradGEMM<OutputTileRows, OutputTileCols, KernelRows, KernelCols, winograd::WinogradRoots::Integers>;
using WinogradConv = typename WinogradBase::template Convolution<T, T>;
- using WeightsTransform = typename WinogradBase::template WeightsTransform<T>;
-
- const ITensor *_weights_hwio;
- ITensor *_output;
- int _matrix_stride;
- int _num_output_channels;
- int _num_input_channels;
+ using WeightsTransform = typename WinogradBase::template WeightsTransform<T, T>;
+
+ std::unique_ptr<WeightsTransform> _transform{ nullptr };
+ const ITensor *_weights_hwio;
+ ITensor *_output;
+ int _matrix_stride;
+ int _num_output_channels;
+ int _num_input_channels;
};
/** NEON kernel to perform Winograd. */
@@ -499,7 +562,7 @@ class NEWinogradLayerConfiguration
{
public:
/** Winograd base kernel */
- using WinogradBase = winograd::WinogradGEMM<OutputTileRows, OutputTileCols, KernelRows, KernelCols>;
+ using WinogradBase = winograd::WinogradGEMM<OutputTileRows, OutputTileCols, KernelRows, KernelCols, winograd::WinogradRoots::Integers>;
/** Winograd convolution kernel */
using WinogradConv = typename WinogradBase::template Convolution<TIn, TOut>;