aboutsummaryrefslogtreecommitdiff
path: root/src/core/GLES_COMPUTE/kernels
diff options
context:
space:
mode:
authorStephen Li <stephen.li@arm.com>2018-01-04 14:13:22 +0800
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:43:42 +0000
commite855c237a5b61c4ed5a5ab79dd4af27385cf72f5 (patch)
treeeb81a77c6c588c8d25937c27249552524791b4d0 /src/core/GLES_COMPUTE/kernels
parent81ce008ebbc6dc19b22034794d12124b58ee334b (diff)
downloadComputeLibrary-e855c237a5b61c4ed5a5ab79dd4af27385cf72f5.tar.gz
APPBROWSER-377: GCConvoutionLayer support for FP16
Change-Id: I801b5e393a16a9f92c062826e6fcfd5982ca7bb3 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/116584 Tested-by: Jenkins <bsgcomp@arm.com> Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
Diffstat (limited to 'src/core/GLES_COMPUTE/kernels')
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCCol2ImKernel.cpp69
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCDepthConcatenateLayerKernel.cpp2
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCDirectConvolutionLayerKernel.cpp2
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCDropoutLayerKernel.cpp2
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCGEMMInterleave4x4Kernel.cpp4
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCGEMMMatrixAccumulateBiasesKernel.cpp2
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCGEMMTranspose1xWKernel.cpp4
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCIm2ColKernel.cpp118
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCTransposeKernel.cpp2
-rw-r--r--src/core/GLES_COMPUTE/kernels/GCWeightsReshapeKernel.cpp146
10 files changed, 281 insertions, 70 deletions
diff --git a/src/core/GLES_COMPUTE/kernels/GCCol2ImKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCCol2ImKernel.cpp
index 492f708a98..af1e34ef59 100644
--- a/src/core/GLES_COMPUTE/kernels/GCCol2ImKernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCCol2ImKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -24,6 +24,7 @@
#include "arm_compute/core/GLES_COMPUTE/kernels/GCCol2ImKernel.h"
+#include "arm_compute/core/AccessWindowStatic.h"
#include "arm_compute/core/Error.h"
#include "arm_compute/core/GLES_COMPUTE/GCHelpers.h"
#include "arm_compute/core/GLES_COMPUTE/GCKernelLibrary.h"
@@ -43,31 +44,50 @@ GCCol2ImKernel::GCCol2ImKernel()
void GCCol2ImKernel::configure(const IGCTensor *input, IGCTensor *output,
std::pair<unsigned int, unsigned int> convolved_dims)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F32);
+ ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(output);
+
+ TensorShape output_shape = input->info()->tensor_shape();
+ output_shape.set(0, convolved_dims.first);
+ output_shape.set(1, convolved_dims.second);
+ output_shape.set(2, input->info()->tensor_shape()[0]);
+
+ // Output auto inizialitation if not yet initialized
+ auto_init_if_empty(*output->info(), input->info()->clone()->set_tensor_shape(output_shape));
+
+ ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(output->info()->tensor_shape(), output_shape);
ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
_input = input;
_output = output;
_convolved_dims = convolved_dims;
+ unsigned int num_elems_processed_per_iteration = 1;
+
// Create kernel
- std::set<std::string> build_opts;
- constexpr unsigned int num_elems_processed_per_iteration = 8;
+ std::set<std::string> build_opts;
+ build_opts.emplace("#define WIDTH_OUTPUT " + support::cpp11::to_string(_convolved_dims.first));
+ std::string dt_name = (input->info()->data_type() == DataType::F32) ? "DATA_TYPE_FP32" : "DATA_TYPE_FP16";
+ build_opts.emplace(("#define " + dt_name));
build_opts.emplace("#define LOCAL_SIZE_X " + support::cpp11::to_string(num_elems_processed_per_iteration));
build_opts.emplace("#define LOCAL_SIZE_Y " + support::cpp11::to_string(num_elems_processed_per_iteration));
- build_opts.emplace("#define LOCAL_SIZE_Z " + support::cpp11::to_string(1));
- build_opts.insert("#define COL2IM");
- _kernel = static_cast<GCKernel>(GCKernelLibrary::get().create_kernel("col2im", build_opts));
+ build_opts.emplace("#define LOCAL_SIZE_Z " + support::cpp11::to_string(num_elems_processed_per_iteration));
- // Set static kernel arguments
- unsigned int idx = num_arguments_per_2D_tensor() + num_arguments_per_3D_tensor();
- _kernel.set_argument(idx++, _convolved_dims.first);
+ _kernel = static_cast<GCKernel>(GCKernelLibrary::get().create_kernel("col2im", build_opts));
// Configure window
- Window win = calculate_max_window(*input->info(), Steps());
+ unsigned int nums = 2;
+ Window win = calculate_max_window(*output->info(), Steps(nums));
- // The GCCol2ImKernel doesn't need padding so update_window_and_padding() can be skipped
- output->info()->set_valid_region(ValidRegion(Coordinates(), output->info()->tensor_shape()));
+ AccessWindowHorizontal output_access(output->info(), 0, 2);
+ const int input_padding = ceil_to_multiple(input->info()->dimension(0), 2) - input->info()->dimension(0);
+
+ AccessWindowStatic input_access(input->info(), 0, 0, input->info()->dimension(0) + input_padding, input->info()->dimension(1) + 1);
+
+ update_window_and_padding(win, input_access,
+ output_access);
+
+ output_access.set_valid_region(win, output->info()->valid_region());
IGCKernel::configure(win);
}
@@ -77,20 +97,25 @@ void GCCol2ImKernel::run(const Window &window)
ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(IGCKernel::window(), window);
- Window slice_in = window.first_slice_window_2D();
- Window slice_out = window.first_slice_window_3D();
-
_kernel.use();
+ Window collapsed_window = window.collapse_if_possible(IGCKernel::window(), Window::DimZ);
+ Window slice = collapsed_window.first_slice_window_3D();
+
+ // Set static kernel arguments
+ unsigned int idx = 2 * num_arguments_per_3D_tensor();
+ //_kernel.set_argument(idx++, _output->info()->strides_in_bytes()[3]);
+ _kernel.set_argument(idx++, uint(_output->info()->dimension(2)));
+ _kernel.set_argument(idx++, _input->info()->strides_in_bytes()[2]);
+
do
{
// Set inputs
- unsigned int idx = 0;
- unsigned int binding = 1;
- add_2D_tensor_argument(idx, _input, binding++, slice_in);
- add_3D_tensor_argument(idx, _output, binding++, slice_out);
+ unsigned int idx = 0;
+ add_2D_tensor_argument(idx, _input, 1, slice);
+ add_3D_tensor_argument(idx, _output, 2, slice);
_kernel.update_shader_params();
- enqueue(*this, slice_in);
+ enqueue(*this, slice);
}
- while(window.slide_window_slice_2D(slice_in) && window.slide_window_slice_3D(slice_out));
+ while(collapsed_window.slide_window_slice_3D(slice));
}
diff --git a/src/core/GLES_COMPUTE/kernels/GCDepthConcatenateLayerKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCDepthConcatenateLayerKernel.cpp
index 4eceab8266..7b1848c32b 100644
--- a/src/core/GLES_COMPUTE/kernels/GCDepthConcatenateLayerKernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCDepthConcatenateLayerKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
diff --git a/src/core/GLES_COMPUTE/kernels/GCDirectConvolutionLayerKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCDirectConvolutionLayerKernel.cpp
index 77423fd8bc..23f1c2eada 100644
--- a/src/core/GLES_COMPUTE/kernels/GCDirectConvolutionLayerKernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCDirectConvolutionLayerKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
diff --git a/src/core/GLES_COMPUTE/kernels/GCDropoutLayerKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCDropoutLayerKernel.cpp
index cd06be2585..8886b84fc0 100644
--- a/src/core/GLES_COMPUTE/kernels/GCDropoutLayerKernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCDropoutLayerKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
diff --git a/src/core/GLES_COMPUTE/kernels/GCGEMMInterleave4x4Kernel.cpp b/src/core/GLES_COMPUTE/kernels/GCGEMMInterleave4x4Kernel.cpp
index ef47e7fd8c..dc86bfb2cc 100644
--- a/src/core/GLES_COMPUTE/kernels/GCGEMMInterleave4x4Kernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCGEMMInterleave4x4Kernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -44,7 +44,7 @@ GCGEMMInterleave4x4Kernel::GCGEMMInterleave4x4Kernel()
void GCGEMMInterleave4x4Kernel::configure(const IGCTensor *input, IGCTensor *output)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F32);
+ ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32);
ARM_COMPUTE_ERROR_ON_NULLPTR(output);
TensorShape output_shape = input->info()->tensor_shape();
diff --git a/src/core/GLES_COMPUTE/kernels/GCGEMMMatrixAccumulateBiasesKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCGEMMMatrixAccumulateBiasesKernel.cpp
index 7ee39346f8..6d856e98c3 100644
--- a/src/core/GLES_COMPUTE/kernels/GCGEMMMatrixAccumulateBiasesKernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCGEMMMatrixAccumulateBiasesKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
diff --git a/src/core/GLES_COMPUTE/kernels/GCGEMMTranspose1xWKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCGEMMTranspose1xWKernel.cpp
index a78446e074..5d9f9c2d3e 100644
--- a/src/core/GLES_COMPUTE/kernels/GCGEMMTranspose1xWKernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCGEMMTranspose1xWKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -40,7 +40,7 @@ using namespace arm_compute;
void GCGEMMTranspose1xWKernel::configure(const IGCTensor *input, IGCTensor *output)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F32);
+ ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32);
ARM_COMPUTE_ERROR_ON_NULLPTR(output);
TensorShape output_shape{ input->info()->tensor_shape() };
diff --git a/src/core/GLES_COMPUTE/kernels/GCIm2ColKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCIm2ColKernel.cpp
index e849891c7c..4ab6f3e89d 100644
--- a/src/core/GLES_COMPUTE/kernels/GCIm2ColKernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCIm2ColKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "arm_compute/core/GLES_COMPUTE/kernels/GCIm2ColKernel.h"
#include "arm_compute/core/AccessWindowStatic.h"
@@ -30,6 +31,7 @@
#include "arm_compute/core/GLES_COMPUTE/IGCTensor.h"
#include "arm_compute/core/GLES_COMPUTE/OpenGLES.h"
#include "arm_compute/core/Helpers.h"
+#include "arm_compute/core/Size2D.h"
#include "arm_compute/core/Types.h"
#include "arm_compute/core/Validate.h"
#include "support/ToolchainSupport.h"
@@ -39,20 +41,40 @@
using namespace arm_compute;
+namespace
+{
+Status validate_arguments(const ITensorInfo *input, const ITensorInfo *output)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(output);
+
+ // Checks performed when output is configured
+ if(output->total_size() != 0)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(input, output);
+ }
+
+ return Status{};
+}
+} // namespace
+
GCIm2ColKernel::GCIm2ColKernel()
- : _input(nullptr), _output(nullptr), _convolved_dims(), _num_elems_processed_per_iteration(1), _run_func(nullptr)
+ : _input(nullptr), _output(nullptr), _convolved_dims(), _kernel_dims(), _num_elems_processed_per_iteration(1), _run_func(nullptr)
{
}
-void GCIm2ColKernel::configure(const IGCTensor *input, IGCTensor *output, std::pair<unsigned int, unsigned int> kernel_dims, const PadStrideInfo &conv_info, bool has_bias)
+void GCIm2ColKernel::configure(const IGCTensor *input, IGCTensor *output, const Size2D &kernel_dims, const PadStrideInfo &conv_info, bool has_bias)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
- ARM_COMPUTE_UNUSED(kernel_dims);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
+
+ // Perform validation step
+ ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), output->info()));
_input = input;
_output = output;
+ // Create kernel
std::set<std::string> build_opts;
std::string dt_name = (input->info()->data_type() == DataType::F32) ? "DATA_TYPE_FP32" : "DATA_TYPE_FP16";
build_opts.emplace("#define LOCAL_SIZE_X " + support::cpp11::to_string(1));
@@ -65,48 +87,52 @@ void GCIm2ColKernel::configure(const IGCTensor *input, IGCTensor *output, std::p
build_opts.emplace("#define HAS_BIAS");
}
- int pad_x = 0;
- int pad_y = 0;
int stride_x = 0;
int stride_y = 0;
- std::tie(pad_x, pad_y) = conv_info.pad();
+
std::tie(stride_x, stride_y) = conv_info.stride();
+ _kernel_dims = std::make_pair(kernel_dims.width, kernel_dims.height);
const bool run_img2col_reduced = (output->info()->dimension(0) == (input->info()->dimension(0) * input->info()->dimension(1) * input->info()->dimension(2))) && (TensorShape::num_max_dimensions >= 4)
&& (std::equal(input->info()->tensor_shape().cbegin() + 3,
input->info()->tensor_shape().cend(),
output->info()->tensor_shape().cbegin() + 1))
- && ((stride_x == 1) && (stride_y == 1) && (pad_x == 0) && (pad_y == 0));
+ && ((stride_x == 1) && (stride_y == 1) && !conv_info.has_padding());
+ std::string kernel_name = "im2col_generic";
if(!run_img2col_reduced)
{
- // this path is currently not used and not validated
- build_opts.insert("#define IM2COL_GENERIC");
+ if(input->info()->data_type() == DataType::F16 && _kernel_dims == std::pair<unsigned int, unsigned int>(1, 1))
+ {
+ build_opts.emplace("#define KERNEL_1x1");
+ }
+
+ build_opts.emplace("#define IM2COL_GENERIC");
_convolved_dims = scaled_dimensions(input->info()->dimension(0), input->info()->dimension(1),
- kernel_dims.first, kernel_dims.second,
+ kernel_dims.width, kernel_dims.height,
conv_info);
- _num_elems_processed_per_iteration = output->info()->dimension(0);
+ _num_elems_processed_per_iteration = 2;
- build_opts.emplace("#define KERNEL_WIDTH " + support::cpp11::to_string(kernel_dims.first));
- build_opts.emplace("#define KERNEL_HEIGHT " + support::cpp11::to_string(kernel_dims.second));
+ build_opts.emplace("#define KERNEL_WIDTH " + support::cpp11::to_string(kernel_dims.width));
+ build_opts.emplace("#define KERNEL_HEIGHT " + support::cpp11::to_string(kernel_dims.height));
build_opts.emplace("#define KERNEL_DEPTH " + support::cpp11::to_string(input->info()->dimension(2)));
build_opts.emplace("#define CONVOLVED_WIDTH " + support::cpp11::to_string(_convolved_dims.first));
build_opts.emplace("#define CONVOLVED_HEIGHT " + support::cpp11::to_string(_convolved_dims.second));
build_opts.emplace("#define STRIDE_X " + support::cpp11::to_string(conv_info.stride().first));
build_opts.emplace("#define STRIDE_Y " + support::cpp11::to_string(conv_info.stride().second));
- build_opts.emplace("#define PAD_X " + support::cpp11::to_string(conv_info.pad().first));
- build_opts.emplace("#define PAD_Y " + support::cpp11::to_string(conv_info.pad().second));
+ build_opts.emplace("#define PAD_LEFT " + support::cpp11::to_string(conv_info.pad_left()));
+ build_opts.emplace("#define PAD_TOP " + support::cpp11::to_string(conv_info.pad_top()));
+ build_opts.emplace("#define PAD_RIGHT " + support::cpp11::to_string(conv_info.pad_right()));
+ build_opts.emplace("#define PAD_BOTTOM " + support::cpp11::to_string(conv_info.pad_bottom()));
build_opts.emplace("#define SRC_WIDTH " + support::cpp11::to_string(input->info()->dimension(0)));
build_opts.emplace("#define SRC_HEIGHT " + support::cpp11::to_string(input->info()->dimension(1)));
- // Create kernel
- _kernel = static_cast<GCKernel>(GCKernelLibrary::get().create_kernel("im2col_generic", build_opts));
-
_run_func = &GCIm2ColKernel::run_generic;
}
else
{
- build_opts.insert("#define IM2COL_REDUCED");
+ build_opts.emplace("#define IM2COL_REDUCED");
+ kernel_name = "im2col_reduced";
if(input->info()->data_type() == DataType::F32)
{
@@ -117,42 +143,47 @@ void GCIm2ColKernel::configure(const IGCTensor *input, IGCTensor *output, std::p
int input_width = input->info()->dimension(0);
int input_height = input->info()->dimension(1);
- build_opts.insert("#define IMAGE_SIZE " + support::cpp11::to_string(input_width * input_height));
+ build_opts.emplace("#define IMAGE_SIZE " + support::cpp11::to_string(input_width * input_height));
if(input_width % 8 == 0)
{
_num_elems_processed_per_iteration = 8;
- build_opts.insert("#define IM2COL_REDUCED_8X");
+ build_opts.emplace("#define IM2COL_REDUCED_8X");
}
else if(input_width % 4 == 0)
{
_num_elems_processed_per_iteration = 4;
- build_opts.insert("#define IM2COL_REDUCED_4X");
+ build_opts.emplace("#define IM2COL_REDUCED_4X");
}
else if(input_width % 2 == 0)
{
_num_elems_processed_per_iteration = 2;
- build_opts.insert("#define IM2COL_REDUCED_2X");
+ build_opts.emplace("#define IM2COL_REDUCED_2X");
}
else
{
_num_elems_processed_per_iteration = 2;
- build_opts.insert("#define IM2COL_REDUCED_GENERIC");
+ build_opts.emplace("#define IM2COL_REDUCED_GENERIC");
}
}
- // Create kernel
- _kernel = static_cast<GCKernel>(GCKernelLibrary::get().create_kernel("im2col_reduced", build_opts));
-
_run_func = &GCIm2ColKernel::run_reduced;
}
+ // Create kernel
+ _kernel = static_cast<GCKernel>(GCKernelLibrary::get().create_kernel(kernel_name, build_opts));
+
// Configure kernel window
Window win = calculate_max_window(*input->info(), Steps(_num_elems_processed_per_iteration));
if(input->info()->data_type() == DataType::F16)
{
// Calculate input right and bottom border
- AccessWindowHorizontal input_access(input->info(), 0, _num_elems_processed_per_iteration);
+ const int input_width = input->info()->dimension(0);
+ const int input_height = input->info()->dimension(1);
+ int input_total_width = input->info()->padding().left + input_width + input->info()->padding().right;
+ int input_padding_right = ceil_to_multiple(input_total_width, _num_elems_processed_per_iteration) - input_total_width;
+ input_total_width = input_width + input_padding_right + input->info()->padding().right;
+ AccessWindowStatic input_access(input->info(), 0, 0, input_total_width, input_height);
// Calculate output right and bottom border
const int output_width = output->info()->dimension(0);
@@ -174,6 +205,15 @@ void GCIm2ColKernel::configure(const IGCTensor *input, IGCTensor *output, std::p
IGCKernel::configure(win);
}
+Status GCIm2ColKernel::validate(const ITensorInfo *input, const ITensorInfo *output, const Size2D &kernel_dims, const PadStrideInfo &conv_info, bool has_bias)
+{
+ ARM_COMPUTE_UNUSED(kernel_dims);
+ ARM_COMPUTE_UNUSED(conv_info);
+ ARM_COMPUTE_UNUSED(has_bias);
+ ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, output));
+ return Status{};
+}
+
void GCIm2ColKernel::run(const Window &window)
{
ARM_COMPUTE_ERROR_ON(_run_func == nullptr);
@@ -187,6 +227,7 @@ void GCIm2ColKernel::run_generic(const Window &window)
// Get initial windows
Window window_collapsed = window.collapse_if_possible(IGCKernel::window(), Window::DimZ);
+
// Change the Z dimension's step back to 1
window_collapsed.set_dimension_step(Window::DimZ, 1);
@@ -198,17 +239,18 @@ void GCIm2ColKernel::run_generic(const Window &window)
slice.set(Window::DimX, Window::Dimension(0, static_cast<int>(_convolved_dims.first), 1));
slice.set(Window::DimY, Window::Dimension(0, static_cast<int>(_convolved_dims.second), 1));
- // Setup input slice
- // The first three dimensions of the input are increased by the inner loops
- slice_in.set(Window::DimX, Window::Dimension(0, 0, 0));
- slice_in.set(Window::DimY, Window::Dimension(0, 0, 0));
- slice_in.set(Window::DimZ, Window::Dimension(0, 0, 0));
-
// Setup output slice
slice_out.set(Window::DimX, Window::Dimension(0, _output->info()->dimension(0), _num_elems_processed_per_iteration));
slice_out.set(Window::DimY, Window::Dimension(0, _output->info()->dimension(1), 1));
slice_out.set(Window::DimZ, Window::Dimension(0, 1, 1));
+ // we need top/left pad to be included in valid region
+ if(_input->info()->data_type() == DataType::F16)
+ {
+ (dynamic_cast<TensorInfo *>(_input->info()))->init(_input->info()->tensor_shape(), _input->info()->num_channels(), _input->info()->data_type(), _input->info()->strides_in_bytes(), 0,
+ _input->info()->total_size(), _input->info()->fixed_point_position());
+ }
+
_kernel.use();
do
@@ -216,8 +258,6 @@ void GCIm2ColKernel::run_generic(const Window &window)
unsigned int idx = 0;
add_3D_tensor_argument(idx, _input, 1, slice_in);
add_2D_tensor_argument(idx, _output, 2, slice_out);
-
- _kernel.set_argument(idx++, static_cast<unsigned int>(_input->info()->dimension(2)));
_kernel.set_argument(idx++, static_cast<unsigned int>(_input->info()->strides_in_bytes()[3]));
_kernel.set_argument(idx++, static_cast<unsigned int>(_output->info()->strides_in_bytes()[3]));
_kernel.update_shader_params();
diff --git a/src/core/GLES_COMPUTE/kernels/GCTransposeKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCTransposeKernel.cpp
index b3a7a90931..bda08e4238 100644
--- a/src/core/GLES_COMPUTE/kernels/GCTransposeKernel.cpp
+++ b/src/core/GLES_COMPUTE/kernels/GCTransposeKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
diff --git a/src/core/GLES_COMPUTE/kernels/GCWeightsReshapeKernel.cpp b/src/core/GLES_COMPUTE/kernels/GCWeightsReshapeKernel.cpp
new file mode 100644
index 0000000000..4c08873dcf
--- /dev/null
+++ b/src/core/GLES_COMPUTE/kernels/GCWeightsReshapeKernel.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/core/GLES_COMPUTE/kernels/GCWeightsReshapeKernel.h"
+
+#include "arm_compute/core/Error.h"
+#include "arm_compute/core/GLES_COMPUTE/GCHelpers.h"
+#include "arm_compute/core/GLES_COMPUTE/GCKernelLibrary.h"
+#include "arm_compute/core/GLES_COMPUTE/IGCTensor.h"
+#include "arm_compute/core/GLES_COMPUTE/OpenGLES.h"
+#include "arm_compute/core/Helpers.h"
+#include "arm_compute/core/Types.h"
+#include "arm_compute/core/Validate.h"
+
+#include "arm_compute/core/GLES_COMPUTE/GCHelpers.h"
+
+using namespace arm_compute;
+using namespace arm_compute::gles_compute;
+
+GCWeightsReshapeKernel::GCWeightsReshapeKernel()
+ : _input(nullptr), _biases(nullptr), _output(nullptr)
+{
+}
+
+void GCWeightsReshapeKernel::configure(const IGCTensor *input, const IGCTensor *biases, IGCTensor *output)
+{
+ ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(output);
+
+ // Calculate output shape
+ TensorShape output_shape{ input->info()->tensor_shape() };
+ output_shape.collapse(3);
+ const size_t tmp_dim = output_shape[0];
+ output_shape.set(0, output_shape[1]);
+ output_shape.set(1, tmp_dim + (biases != nullptr ? 1 : 0));
+
+ // Output tensor auto inizialitation if not yet initialized
+ auto_init_if_empty(*output->info(), input->info()->clone()->set_tensor_shape(output_shape));
+
+ ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
+
+ if(biases != nullptr)
+ {
+ ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, biases);
+ ARM_COMPUTE_ERROR_ON((input->info()->num_dimensions() == 4) && (biases->info()->num_dimensions() != 1));
+ ARM_COMPUTE_ERROR_ON((input->info()->num_dimensions() == 5) && (biases->info()->num_dimensions() != 2));
+ ARM_COMPUTE_ERROR_ON((input->info()->num_dimensions() == 4) && (biases->info()->dimension(0) != input->info()->tensor_shape()[3]));
+ ARM_COMPUTE_ERROR_ON((input->info()->num_dimensions() == 5) && (biases->info()->dimension(0) != input->info()->tensor_shape()[3] || biases->info()->dimension(1) != input->info()->tensor_shape()[4]));
+ }
+
+ _biases = biases;
+ _output = output;
+ _input = input;
+
+ // Create build options
+ std::set<std::string> build_opts;
+ std::string dt_name = (input->info()->data_type() == DataType::F32) ? "DATA_TYPE_FP32" : "DATA_TYPE_FP16";
+ build_opts.emplace("#define " + dt_name);
+ build_opts.emplace("#define LOCAL_SIZE_X " + support::cpp11::to_string(1));
+ build_opts.emplace("#define LOCAL_SIZE_Y " + support::cpp11::to_string(1));
+ build_opts.emplace("#define LOCAL_SIZE_Z " + support::cpp11::to_string(1));
+ build_opts.emplace("#define RESHAPE_TO_COLUMNS");
+ if(biases != nullptr)
+ {
+ build_opts.emplace("#define HAS_BIAS");
+ }
+
+ // Create kernel
+ _kernel = static_cast<GCKernel>(GCKernelLibrary::get().create_kernel("reshape_to_columns", build_opts));
+
+ // Set static arguments
+ unsigned int idx = num_arguments_per_3D_tensor() + num_arguments_per_2D_tensor();
+ idx += (biases != nullptr) ? num_arguments_per_1D_tensor() : 0;
+ _kernel.set_argument(idx++, _input->info()->dimension(0));
+ _kernel.set_argument(idx++, _input->info()->dimension(1));
+ _kernel.set_argument(idx++, _input->info()->dimension(2));
+ _kernel.set_argument(idx++, _input->info()->dimension(3));
+
+ // Configure window
+ Window win = calculate_max_window(*input->info(), Steps());
+
+ // The GCWeightsReshapeKernel doesn't need padding so update_window_and_padding() can be skipped
+ output->info()->set_valid_region(ValidRegion(Coordinates(), output->info()->tensor_shape()));
+ IGCKernel::configure(win);
+}
+
+void GCWeightsReshapeKernel::run(const Window &window)
+{
+ ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
+ ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(IGCKernel::window(), window);
+
+ Window out_window;
+ out_window.use_tensor_dimensions(_output->info()->tensor_shape());
+
+ Window in_slice = window.first_slice_window_3D();
+ Window out_slice = out_window.first_slice_window_2D();
+
+ Window biases_window;
+ Window biases_slice;
+
+ if(_biases != nullptr)
+ {
+ biases_window.use_tensor_dimensions(_biases->info()->tensor_shape());
+ biases_slice = biases_window.first_slice_window_1D();
+ }
+
+ _kernel.use();
+
+ do
+ {
+ // Set arguments
+ unsigned idx = 0;
+ add_3D_tensor_argument(idx, _input, 1, in_slice);
+ add_2D_tensor_argument(idx, _output, 2, out_slice);
+ if(_biases != nullptr)
+ {
+ add_1D_tensor_argument(idx, _biases, 3, biases_slice);
+ biases_window.slide_window_slice_1D(biases_slice);
+ }
+
+ _kernel.update_shader_params();
+ // Run kernel
+ enqueue(*this, in_slice);
+ }
+ while(window.slide_window_slice_4D(in_slice) && out_window.slide_window_slice_2D(out_slice));
+}