aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgios Pinitas <georgios.pinitas@arm.com>2017-11-14 15:32:57 +0000
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:35:24 +0000
commit30902ed3befd225cb3a6915223d0941949b8d265 (patch)
tree6f701094ae52e8e4dc41b993febbff404e660c82
parent77f0f879f8a9371e50fb1c5b2b5f7252b839883c (diff)
downloadComputeLibrary-30902ed3befd225cb3a6915223d0941949b8d265.tar.gz
COMPMID-617: Add validation methods to ML CL functions.
Adds validation support to: - CLDirectConvolution - CLNormalizationLayer - CLSoftmaxLayer Change-Id: I9bd1e925e6db057c799169405f82ed21d20b87ee Reviewed-on: http://mpd-gerrit.cambridge.arm.com/95939 Reviewed-by: Anthony Barbier <anthony.barbier@arm.com> Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com>
-rw-r--r--arm_compute/core/CL/kernels/CLDirectConvolutionLayerKernel.h19
-rw-r--r--arm_compute/core/CL/kernels/CLNormalizationLayerKernel.h11
-rw-r--r--arm_compute/core/CL/kernels/CLSoftmaxLayerKernel.h37
-rw-r--r--arm_compute/core/ITensorInfo.h5
-rw-r--r--arm_compute/core/SubTensorInfo.h6
-rw-r--r--arm_compute/core/TensorInfo.h3
-rw-r--r--arm_compute/runtime/CL/functions/CLDirectConvolutionLayer.h14
-rw-r--r--arm_compute/runtime/CL/functions/CLNormalizationLayer.h10
-rw-r--r--arm_compute/runtime/CL/functions/CLSoftmaxLayer.h8
-rw-r--r--src/core/CL/kernels/CLDirectConvolutionLayerKernel.cpp114
-rw-r--r--src/core/CL/kernels/CLNormalizationLayerKernel.cpp42
-rw-r--r--src/core/CL/kernels/CLSoftmaxLayerKernel.cpp169
-rw-r--r--src/core/TensorInfo.cpp11
-rw-r--r--src/runtime/CL/functions/CLDirectConvolutionLayer.cpp5
-rw-r--r--src/runtime/CL/functions/CLNormalizationLayer.cpp5
-rw-r--r--src/runtime/CL/functions/CLSoftmaxLayer.cpp37
-rw-r--r--tests/validation/CL/DirectConvolutionLayer.cpp67
-rw-r--r--tests/validation/CL/NormalizationLayer.cpp32
-rw-r--r--tests/validation/CL/SoftmaxLayer.cpp31
19 files changed, 527 insertions, 99 deletions
diff --git a/arm_compute/core/CL/kernels/CLDirectConvolutionLayerKernel.h b/arm_compute/core/CL/kernels/CLDirectConvolutionLayerKernel.h
index da786d71df..0564553b45 100644
--- a/arm_compute/core/CL/kernels/CLDirectConvolutionLayerKernel.h
+++ b/arm_compute/core/CL/kernels/CLDirectConvolutionLayerKernel.h
@@ -67,12 +67,25 @@ public:
* @param[in] conv_info Contains padding and stride information described in @ref PadStrideInfo.
*/
void configure(const ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info);
-
- // Inherited methods overridden:
- BorderSize border_size() const override;
+ /** Static function to check if given info will lead to a valid configuration of @ref CLDirectConvolutionLayerKernel
+ *
+ * @param[in] input The input tensor to convolve. 3 lower dimensions represent a single input [width, height, IFM],
+ * while every optional dimension from 4 and above represent a batch of inputs. Data types supported: QS8/QASYMM8/QS16/F16/F32.
+ * @param[in] weights Weights tensor. Weights are 4D tensor with dimensions [kernel_x, kernel_y, IFM, OFM].
+ * The 3rd dimension must be the same as the input's volume 3rd dimension.
+ * Data type supported:Same as @p input.
+ * @param[in] biases Biases tensor. Biases are 1D tensor with dimension [OFM]. Data type supported: Same as @p input.
+ * @param[in] output Output tensor.
+ * The 3rd dimensions must be equal to the 4th dimension of the @p kernels tensor. Data types supported: Same as @p input.
+ * @param[in] conv_info Contains padding and stride information described in @ref PadStrideInfo.
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info);
// Inherited methods overridden:
void run(const Window &window, cl::CommandQueue &queue) override;
+ BorderSize border_size() const override;
private:
const ICLTensor *_input;
diff --git a/arm_compute/core/CL/kernels/CLNormalizationLayerKernel.h b/arm_compute/core/CL/kernels/CLNormalizationLayerKernel.h
index f74f7514ee..38daac69b1 100644
--- a/arm_compute/core/CL/kernels/CLNormalizationLayerKernel.h
+++ b/arm_compute/core/CL/kernels/CLNormalizationLayerKernel.h
@@ -45,7 +45,6 @@ public:
CLNormalizationLayerKernel(CLNormalizationLayerKernel &&) = default;
/** Default move assignment operator. */
CLNormalizationLayerKernel &operator=(CLNormalizationLayerKernel &&) = default;
-
/** Set the input and output tensors.
*
* @param[in] input Source tensor. 3 lower dims represent a single input with dimensions [width, height, IFM],
@@ -54,6 +53,16 @@ public:
* @param[in] norm_info Normalization layer information like the normalization type, normalization size and other parameters.
*/
void configure(const ICLTensor *input, ICLTensor *output, NormalizationLayerInfo norm_info);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLNormalizationLayerKernel
+ *
+ * @param[in] input Source tensor. 3 lower dims represent a single input with dimensions [width, height, IFM],
+ * and an optional 4th dimension for batch of inputs. Data types supported: QS8/QS16/F16/F32.
+ * @param[in] output Destination tensor. Output will have the same number of dimensions as input. Data types supported: same as @p input.
+ * @param[in] norm_info Normalization layer information like the normalization type, normalization size and other parameters.
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *output, NormalizationLayerInfo norm_info);
// Inherited methods overridden:
void run(const Window &window, cl::CommandQueue &queue) override;
diff --git a/arm_compute/core/CL/kernels/CLSoftmaxLayerKernel.h b/arm_compute/core/CL/kernels/CLSoftmaxLayerKernel.h
index ab550aa52a..b0adb67578 100644
--- a/arm_compute/core/CL/kernels/CLSoftmaxLayerKernel.h
+++ b/arm_compute/core/CL/kernels/CLSoftmaxLayerKernel.h
@@ -42,6 +42,14 @@ public:
* @param[out] output Destination tensor. Data types supported: same as @p input
*/
void configure(const ICLTensor *input, ICLTensor *output);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLLogits1DMaxKernel
+ *
+ * @param[in] input Source tensor. Data types supported: QS8/QASYMM8/QS16/F16/F32
+ * @param[in] output Destination tensor. Data types supported: same as @p input
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *output);
};
/** Interface for shifting, exponentiating and summing the logits */
@@ -67,6 +75,16 @@ public:
* @param[in] beta (Optional) A scaling factor for the exponent. Defaults to 1.0
*/
void configure(const ICLTensor *input, const ICLTensor *max, ICLTensor *output, ICLTensor *sum, float beta = 1.0f);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLLogits1DShiftExpSumKernel
+ *
+ * @param[in] input Source tensor. Data types supported: QS8/QASYMM8/QS16/F16/F32
+ * @param[in] max Max values tensor. Data types supported: same as @p input
+ * @param[in] output Destination tensor. Data types supported: S32 for QASYMM8 @p input, or same as @p input
+ * @param[in] sum Sum of 1D logits tensor. Data types supported: S32 for QASYMM8 @p input, or same as @p input
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *max, const ITensorInfo *output, const ITensorInfo *sum);
// Inherited methods overridden:
void run(const Window &window, cl::CommandQueue &queue) override;
@@ -104,6 +122,16 @@ public:
* @param[in] beta (Optional) A scaling factor for the exponent. Defaults to 1.f
*/
void configure(const ICLTensor *input, ICLTensor *max, ICLTensor *output, ICLTensor *sum, float beta = 1.0f);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLLogits1DMaxShiftExpSumKernel
+ *
+ * @param[in] input Source tensor. Data types supported: QS8/QS16/F16/F32
+ * @param[in] max Max values tensor. Data types supported: same as @p input
+ * @param[in] output Destination tensor. Data types supported: same as @p input
+ * @param[in] sum Sum of 1D logits tensor. Data types supported: same as @p input
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *max, const ITensorInfo *output, const ITensorInfo *sum);
/** Checks if the given size is eligible for parallel reduction
*
* @note Serial reduction is launched for width < (_grid_size * _serial_vector_size).
@@ -152,6 +180,15 @@ public:
* @param[in] beta (Optional) A scaling factor for the exponent. (Default = 1.0)
*/
void configure(const ICLTensor *input, const ICLTensor *sum, ICLTensor *output, float beta = 1.0f);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLLogits1DNormKernel
+ *
+ * @param[in] input Source tensor. Data types supported: QS8/QS16/S32/F16/F32
+ * @param[in] sum Sum tensor. Dimensions should be dim(input)-1. Data types supported: same as @p input
+ * @param[in] output Destination tensor. Data types supported: QASYMM8 for S32 @p input, or same as @p input
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *sum, const ITensorInfo *output);
// Inherited methods overridden:
void run(const Window &window, cl::CommandQueue &queue) override;
diff --git a/arm_compute/core/ITensorInfo.h b/arm_compute/core/ITensorInfo.h
index 5e8d4e8136..1bc0a80bac 100644
--- a/arm_compute/core/ITensorInfo.h
+++ b/arm_compute/core/ITensorInfo.h
@@ -96,6 +96,11 @@ public:
* @return Reference to this ITensorInfo object
*/
virtual ITensorInfo &set_quantization_info(QuantizationInfo quantization_info) = 0;
+ /** Resets the padding settings of the tensor.
+ *
+ * @return Reference to this ITensorInfo object
+ */
+ virtual ITensorInfo &reset_padding() = 0;
/** Update the offset to the first element and the strides to automatically computed values.
*
* @note The padding used by this method is really conservative so that the tensor can be used for most functions.
diff --git a/arm_compute/core/SubTensorInfo.h b/arm_compute/core/SubTensorInfo.h
index 5fec11a2e8..b8a36854dc 100644
--- a/arm_compute/core/SubTensorInfo.h
+++ b/arm_compute/core/SubTensorInfo.h
@@ -104,6 +104,12 @@ public:
_parent->set_quantization_info(quantization_info);
return *this;
}
+ ITensorInfo &reset_padding() override
+ {
+ ARM_COMPUTE_ERROR_ON(_parent == nullptr);
+ _parent->reset_padding();
+ return *this;
+ }
bool auto_padding() override
{
ARM_COMPUTE_ERROR_ON(_parent == nullptr);
diff --git a/arm_compute/core/TensorInfo.h b/arm_compute/core/TensorInfo.h
index 2383f2db21..5fd6c47818 100644
--- a/arm_compute/core/TensorInfo.h
+++ b/arm_compute/core/TensorInfo.h
@@ -220,7 +220,8 @@ public:
ITensorInfo &set_tensor_shape(TensorShape shape) override;
ITensorInfo &set_fixed_point_position(int fixed_point_position) override;
ITensorInfo &set_quantization_info(QuantizationInfo quantization_info) override;
- bool auto_padding() override;
+ ITensorInfo &reset_padding() override;
+ bool auto_padding() override;
bool extend_padding(const PaddingSize &padding) override;
size_t dimension(size_t index) const override
{
diff --git a/arm_compute/runtime/CL/functions/CLDirectConvolutionLayer.h b/arm_compute/runtime/CL/functions/CLDirectConvolutionLayer.h
index 45fd0c7365..cfb41002cf 100644
--- a/arm_compute/runtime/CL/functions/CLDirectConvolutionLayer.h
+++ b/arm_compute/runtime/CL/functions/CLDirectConvolutionLayer.h
@@ -54,6 +54,20 @@ public:
* @param[in] conv_info Contains padding and stride information described in @ref PadStrideInfo.
*/
void configure(ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLDirectConvolutionLayer
+ *
+ * @param[in] input Source tensor. 3 lower dimensions represent a single input [width, height, IFM],
+ * while every optional dimension from 4 and above represent a batch of inputs.
+ * Data types supported: QS8/QASYMM8/QS16/F16/F32.
+ * @param[in] weights Weights tensor. Weights are 4D tensor with dimensions [kernel_x, kernel_y, IFM, OFM]. Data type supported:Same as @p input.
+ * @param[in] biases Biases tensor. Shared biases supported. Biases are 1D tensor with dimensions [OFM]. Data type supported:Same as @p input.
+ * @param[in] output Destination tensor. 3 lower dimensions represent a single output [width, height, OFM], while the rest represent batch of outputs.
+ * Data types supported: Same as @p input.
+ * @param[in] conv_info Contains padding and stride information described in @ref PadStrideInfo.
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info);
// Inherited methods overridden:
void run() override;
diff --git a/arm_compute/runtime/CL/functions/CLNormalizationLayer.h b/arm_compute/runtime/CL/functions/CLNormalizationLayer.h
index 1e0b27ae43..7e18ce511c 100644
--- a/arm_compute/runtime/CL/functions/CLNormalizationLayer.h
+++ b/arm_compute/runtime/CL/functions/CLNormalizationLayer.h
@@ -56,6 +56,16 @@ public:
* @param[in] norm_info Normalization layer information like the normalization type, normalization size and other parameters.
*/
void configure(ICLTensor *input, ICLTensor *output, const NormalizationLayerInfo &norm_info);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLNormalizationLayer
+ *
+ * @param[in] input Source tensor. 3 lower dims represent a single input with dimensions [width, height, IFM],
+ * and an optional 4th dimension for batch of inputs. Data types supported: F16/F32
+ * @param[in] output Destination tensor. Dimensions, data type and number of channels must match the input ones.
+ * @param[in] norm_info Normalization layer information like the normalization type, normalization size and other parameters.
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *output, const NormalizationLayerInfo &norm_info);
// Inherited methods overridden:
void run() override;
diff --git a/arm_compute/runtime/CL/functions/CLSoftmaxLayer.h b/arm_compute/runtime/CL/functions/CLSoftmaxLayer.h
index ab1b1ab3f9..b5f1abce31 100644
--- a/arm_compute/runtime/CL/functions/CLSoftmaxLayer.h
+++ b/arm_compute/runtime/CL/functions/CLSoftmaxLayer.h
@@ -58,6 +58,14 @@ public:
* @param[in] beta (Optional) A scaling factor for the exponent. Defaults to 1.f
*/
void configure(const ICLTensor *input, ICLTensor *output, float beta = 1.0f);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLSoftmaxLayer
+ *
+ * @param[in] input Source tensor. Data types supported: QS8/QASYMM8/QS16/F16/F32
+ * @param[in] output Destination tensor. Data types supported: same as @p input
+ *
+ * @return an error status
+ */
+ static Error validate(const ITensorInfo *input, const ITensorInfo *output);
// Inherited methods overridden:
void run() override;
diff --git a/src/core/CL/kernels/CLDirectConvolutionLayerKernel.cpp b/src/core/CL/kernels/CLDirectConvolutionLayerKernel.cpp
index d0b5b9373f..e1901af217 100644
--- a/src/core/CL/kernels/CLDirectConvolutionLayerKernel.cpp
+++ b/src/core/CL/kernels/CLDirectConvolutionLayerKernel.cpp
@@ -39,6 +39,29 @@
using namespace arm_compute;
+namespace
+{
+/** Calculates expected output shape dimension
+ *
+ * @param[in] Input shape
+ *
+ * @return Expected output shape
+ */
+TensorShape get_output_shape(TensorShape input_shape, TensorShape weights_shape, PadStrideInfo conv_info)
+{
+ unsigned int output_width = 0;
+ unsigned int output_height = 0;
+ std::tie(output_width, output_height) = scaled_dimensions(input_shape.x(), input_shape.y(), weights_shape.x(), weights_shape.y(), conv_info);
+
+ TensorShape output_shape = input_shape;
+ output_shape.set(0, output_width);
+ output_shape.set(1, output_height);
+ output_shape.set(2, weights_shape[3]);
+
+ return output_shape;
+}
+} // namespace
+
CLDirectConvolutionLayerKernel::CLDirectConvolutionLayerKernel()
: _input(nullptr), _biases(nullptr), _weights(nullptr), _output(nullptr), _border_size(0), _conv_pad_x(0), _conv_pad_y(0), _conv_stride_x(0), _conv_stride_y(0)
{
@@ -51,44 +74,13 @@ BorderSize CLDirectConvolutionLayerKernel::border_size() const
void CLDirectConvolutionLayerKernel::configure(const ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::QS8, DataType::QS16, DataType::F16, DataType::F32);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights);
- ARM_COMPUTE_ERROR_ON_MSG(weights->info()->dimension(0) != weights->info()->dimension(1),
- "Weights should have same width as length");
- ARM_COMPUTE_ERROR_ON_MSG(weights->info()->dimension(0) != 1 && weights->info()->dimension(0) != 3 && weights->info()->dimension(0) != 5,
- "Kernel sizes other than 1x1, 3x3 or 5x5 are not supported");
- ARM_COMPUTE_ERROR_ON(weights->info()->dimension(2) != input->info()->dimension(2));
- ARM_COMPUTE_ERROR_ON(weights->info()->dimension(0) != weights->info()->dimension(1));
- ARM_COMPUTE_ERROR_ON(weights->info()->num_dimensions() > 4);
- ARM_COMPUTE_ERROR_ON_MSG((weights->info()->dimension(0) == 1) && std::get<0>(conv_info.stride()) > 3, "Strides larger than 3 not supported for 1x1 convolution.");
- ARM_COMPUTE_ERROR_ON_MSG((weights->info()->dimension(0) == 3 || weights->info()->dimension(0) == 5) && std::get<0>(conv_info.stride()) > 2, "Strides larger than 2 not supported for 3x3 convolution.");
-
- if(biases != nullptr)
- {
- if(is_data_type_quantized_asymmetric(input->info()->data_type()))
- {
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(biases, 1, DataType::S32);
- }
- else
- {
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(weights, biases);
- }
- ARM_COMPUTE_ERROR_ON(biases->info()->dimension(0) != weights->info()->dimension(3));
- ARM_COMPUTE_ERROR_ON(biases->info()->num_dimensions() > 1);
- }
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
const unsigned int kernel_size = weights->info()->dimension(0);
const DataType data_type = input->info()->data_type();
// Get convolved dimensions
- unsigned int output_width = 0;
- unsigned int output_height = 0;
- std::tie(output_width, output_height) = scaled_dimensions(input->info()->dimension(0), input->info()->dimension(1), kernel_size, kernel_size, conv_info);
-
- TensorShape output_shape = input->info()->tensor_shape();
- output_shape.set(0, output_width);
- output_shape.set(1, output_height);
- output_shape.set(2, weights->info()->dimension(3));
+ TensorShape output_shape = get_output_shape(input->info()->tensor_shape(), weights->info()->tensor_shape(), conv_info);
// Output auto inizialitation if not yet initialized
auto_init_if_empty(*output->info(),
@@ -98,9 +90,12 @@ void CLDirectConvolutionLayerKernel::configure(const ICLTensor *input, const ICL
input->info()->fixed_point_position(),
input->info()->quantization_info());
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(output->info()->tensor_shape(), output_shape);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(input, output);
+ // Perform validation step
+ ARM_COMPUTE_ERROR_THROW_ON(CLDirectConvolutionLayerKernel::validate(input->info(),
+ weights->info(),
+ (biases != nullptr) ? biases->info() : nullptr,
+ output->info(),
+ conv_info));
_conv_stride_x = std::get<0>(conv_info.stride());
_conv_stride_y = std::get<1>(conv_info.stride());
@@ -267,6 +262,53 @@ void CLDirectConvolutionLayerKernel::configure(const ICLTensor *input, const ICL
_config_id += support::cpp11::to_string(output->info()->dimension(1));
}
+Error CLDirectConvolutionLayerKernel::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QASYMM8, DataType::QS16, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights);
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights->dimension(0) != weights->dimension(1),
+ "Weights should have same width as length");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights->dimension(0) != 1 && weights->dimension(0) != 3 && weights->dimension(0) != 5,
+ "Kernel sizes other than 1x1, 3x3 or 5x5 are not supported");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights->dimension(2) != input->dimension(2),
+ "Weights feature map dimension should match the respective input's one");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights->dimension(0) != weights->dimension(1),
+ "Only rectangular weights are supported!");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights->num_dimensions() > 4,
+ "Weights can be at most 4 dimensional");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG((weights->dimension(0) == 1) && std::get<0>(conv_info.stride()) > 3,
+ "Strides larger than 3 not supported for 1x1 convolution.");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG((weights->dimension(0) == 3 || weights->dimension(0) == 5) && std::get<0>(conv_info.stride()) > 2,
+ "Strides larger than 2 not supported for 3x3 convolution.");
+
+ if(biases != nullptr)
+ {
+ if(is_data_type_quantized_asymmetric(input->data_type()))
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(biases, 1, DataType::S32);
+ }
+ else
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(weights, biases);
+ }
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(biases->dimension(0) != weights->dimension(3),
+ "Biases size and number of input feature maps should match");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(biases->num_dimensions() > 1,
+ "Biases should be one dimensional");
+ }
+
+ // Checks performed when output is configured
+ if(output->total_size() != 0)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output->tensor_shape(),
+ get_output_shape(input->tensor_shape(), weights->tensor_shape(), conv_info));
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(input, output);
+ }
+
+ return Error{};
+}
+
void CLDirectConvolutionLayerKernel::run(const Window &window, cl::CommandQueue &queue)
{
ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
diff --git a/src/core/CL/kernels/CLNormalizationLayerKernel.cpp b/src/core/CL/kernels/CLNormalizationLayerKernel.cpp
index 5d91065783..12e2ca2196 100644
--- a/src/core/CL/kernels/CLNormalizationLayerKernel.cpp
+++ b/src/core/CL/kernels/CLNormalizationLayerKernel.cpp
@@ -47,23 +47,13 @@ BorderSize CLNormalizationLayerKernel::border_size() const
void CLNormalizationLayerKernel::configure(const ICLTensor *input, ICLTensor *output, NormalizationLayerInfo norm_info)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::F16, DataType::F32);
- ARM_COMPUTE_ERROR_ON_NULLPTR(output);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
// Output tensor auto initialization if not yet initialized
auto_init_if_empty(*output->info(), input->info()->tensor_shape(), 1, input->info()->data_type(), input->info()->fixed_point_position());
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(input, output);
- ARM_COMPUTE_ERROR_ON_MSG(!(norm_info.norm_size() % 2), "Normalization size should be odd");
- ARM_COMPUTE_ERROR_ON_MSG(norm_info.type() == NormType::IN_MAP_2D, "2D In-Map Normalization not implemented");
- if(is_data_type_fixed_point(input->info()->data_type()))
- {
- ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(input, output);
- ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(norm_info.beta(), input);
- ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(norm_info.kappa(), input);
- ARM_COMPUTE_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(norm_info.scale_coeff(), input);
- }
+ // Perform validation step
+ ARM_COMPUTE_ERROR_THROW_ON(CLNormalizationLayerKernel::validate(input->info(), output->info(), norm_info));
_input = input;
_output = output;
@@ -118,6 +108,32 @@ void CLNormalizationLayerKernel::configure(const ICLTensor *input, ICLTensor *ou
_config_id += support::cpp11::to_string(input->info()->dimension(1));
}
+Error CLNormalizationLayerKernel::validate(const ITensorInfo *input, const ITensorInfo *output, NormalizationLayerInfo norm_info)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(output);
+
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(!(norm_info.norm_size() % 2), "Normalization size should be odd");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(norm_info.type() == NormType::IN_MAP_2D, "2D In-Map Normalization not implemented");
+
+ if(is_data_type_fixed_point(input->data_type()))
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(norm_info.beta(), input);
+ ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(norm_info.kappa(), input);
+ ARM_COMPUTE_RETURN_ERROR_ON_VALUE_NOT_REPRESENTABLE_IN_FIXED_POINT(norm_info.scale_coeff(), input);
+ }
+
+ // 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_SHAPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(input, output);
+ }
+
+ return Error{};
+}
+
void CLNormalizationLayerKernel::run(const Window &window, cl::CommandQueue &queue)
{
ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
diff --git a/src/core/CL/kernels/CLSoftmaxLayerKernel.cpp b/src/core/CL/kernels/CLSoftmaxLayerKernel.cpp
index 3eae9e5749..53a78f7c99 100644
--- a/src/core/CL/kernels/CLSoftmaxLayerKernel.cpp
+++ b/src/core/CL/kernels/CLSoftmaxLayerKernel.cpp
@@ -39,6 +39,7 @@
#include <string>
using namespace arm_compute;
+
namespace
{
/** Calculates softmax parameters from the quantized input scale and scaling factor for the exponent and places them as build options.
@@ -81,8 +82,7 @@ CLBuildOptions prepare_quantized_softmax_build_options(float input_scale, float
void CLLogits1DMaxKernel::configure(const ICLTensor *input, ICLTensor *output)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QASYMM8, DataType::QS16, DataType::F16, DataType::F32);
- ARM_COMPUTE_ERROR_ON_NULLPTR(output);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
// Softmax across the x dimension
TensorShape output_shape{ input->info()->tensor_shape() };
@@ -96,9 +96,8 @@ void CLLogits1DMaxKernel::configure(const ICLTensor *input, ICLTensor *output)
input->info()->fixed_point_position(),
input->info()->quantization_info());
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, output);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DIMENSIONS(output->info()->tensor_shape(), output_shape);
+ // Perform validation step
+ ARM_COMPUTE_ERROR_THROW_ON(CLLogits1DMaxKernel::validate(input->info(), output->info()));
_input = input;
_output = output;
@@ -146,6 +145,26 @@ void CLLogits1DMaxKernel::configure(const ICLTensor *input, ICLTensor *output)
_config_id += support::cpp11::to_string(input->info()->dimension(1));
}
+Error CLLogits1DMaxKernel::validate(const ITensorInfo *input, const ITensorInfo *output)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QASYMM8, DataType::QS16, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(output);
+
+ // Checks performed when output is configured
+ if(output->total_size() != 0)
+ {
+ // Softmax across the x dimension
+ TensorShape output_shape{ input->tensor_shape() };
+ output_shape.set(0, 1);
+
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output->tensor_shape(), output_shape);
+ }
+
+ return Error{};
+}
+
CLLogits1DShiftExpSumKernel::CLLogits1DShiftExpSumKernel()
: _input(nullptr), _max(nullptr), _output(nullptr), _sum(nullptr)
{
@@ -153,8 +172,7 @@ CLLogits1DShiftExpSumKernel::CLLogits1DShiftExpSumKernel()
void CLLogits1DShiftExpSumKernel::configure(const ICLTensor *input, const ICLTensor *max, ICLTensor *output, ICLTensor *sum, float beta)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QASYMM8, DataType::QS16, DataType::F16, DataType::F32);
- ARM_COMPUTE_ERROR_ON_NULLPTR(max, sum, output);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input, max, sum, output);
const bool is_quantized_asymmetric = is_data_type_quantized_asymmetric(input->info()->data_type());
const DataType tmp_data_type = is_quantized_asymmetric ? DataType::S32 : input->info()->data_type();
@@ -163,18 +181,8 @@ void CLLogits1DShiftExpSumKernel::configure(const ICLTensor *input, const ICLTen
auto_init_if_empty(*sum->info(), max->info()->tensor_shape(), 1, tmp_data_type, input->info()->fixed_point_position());
auto_init_if_empty(*output->info(), input->info()->tensor_shape(), 1, tmp_data_type, input->info()->fixed_point_position());
- ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(input, output);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(max, sum);
- if(is_quantized_asymmetric)
- {
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, max);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(output, sum);
- }
- else
- {
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output, max, sum);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, output, max, sum);
- }
+ // Perform validation step
+ ARM_COMPUTE_ERROR_THROW_ON(CLLogits1DShiftExpSumKernel::validate(input->info(), max->info(), output->info(), sum->info()));
_input = input;
_max = max;
@@ -224,6 +232,46 @@ void CLLogits1DShiftExpSumKernel::configure(const ICLTensor *input, const ICLTen
ICLKernel::configure(win);
}
+Error CLLogits1DShiftExpSumKernel::validate(const ITensorInfo *input, const ITensorInfo *max, const ITensorInfo *output, const ITensorInfo *sum)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QASYMM8, DataType::QS16, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(max, sum, output);
+
+ const bool is_quantized_asymmetric = is_data_type_quantized_asymmetric(input->data_type());
+
+ // Checks performed when output is configured
+ if(output->total_size() != 0)
+ {
+ if(is_quantized_asymmetric)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output, 1, DataType::S32);
+ }
+ else
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
+ }
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, output);
+ }
+
+ // Checks performed when sum is configured
+ if(sum->total_size() != 0)
+ {
+ if(is_quantized_asymmetric)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(sum, 1, DataType::S32);
+ }
+ else
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(max, sum);
+ }
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(max, sum);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(max, sum);
+ }
+
+ return Error{};
+}
+
void CLLogits1DShiftExpSumKernel::run(const Window &window, cl::CommandQueue &queue)
{
ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
@@ -259,17 +307,14 @@ CLLogits1DMaxShiftExpSumKernel::CLLogits1DMaxShiftExpSumKernel()
void CLLogits1DMaxShiftExpSumKernel::configure(const ICLTensor *input, ICLTensor *max, ICLTensor *output, ICLTensor *sum, float beta)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::F16, DataType::F32);
- ARM_COMPUTE_ERROR_ON_NULLPTR(max, sum, output);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input, max, sum, output);
// Output auto initialization if not yet initialized
auto_init_if_empty(*sum->info(), max->info()->tensor_shape(), 1, input->info()->data_type(), input->info()->fixed_point_position());
auto_init_if_empty(*output->info(), input->info()->tensor_shape(), 1, input->info()->data_type(), input->info()->fixed_point_position());
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output, max, sum);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, output, max, sum);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(input, output);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(max, sum);
+ // Perform validation step
+ ARM_COMPUTE_ERROR_THROW_ON(CLLogits1DMaxShiftExpSumKernel::validate(input->info(), max->info(), output->info(), sum->info()));
_input = input;
_max = max;
@@ -336,6 +381,33 @@ void CLLogits1DMaxShiftExpSumKernel::configure(const ICLTensor *input, ICLTensor
ICLKernel::configure(win);
}
+Error CLLogits1DMaxShiftExpSumKernel::validate(const ITensorInfo *input, const ITensorInfo *max, const ITensorInfo *output, const ITensorInfo *sum)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(max, sum, output);
+
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, max);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, max);
+
+ // 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_SHAPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, output);
+ }
+
+ // Checks performed when sum is configured
+ if(sum->total_size() != 0)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(max, sum);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(max, sum);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(max, sum);
+ }
+
+ return Error{};
+}
+
CLLogits1DMaxShiftExpSumKernel::ParallelReductionInfo CLLogits1DMaxShiftExpSumKernel::is_parallel_reduction(size_t size)
{
bool is_parallel_reduction = (size >= (_grid_size * _serial_vector_size)) && (_grid_size > 1);
@@ -382,10 +454,7 @@ CLLogits1DNormKernel::CLLogits1DNormKernel()
void CLLogits1DNormKernel::configure(const ICLTensor *input, const ICLTensor *sum, ICLTensor *output, float beta)
{
- ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::S32, DataType::F16, DataType::F32);
- ARM_COMPUTE_ERROR_ON_NULLPTR(sum, output);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, sum);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, sum);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input, sum, output);
// Note: output should always have a scale of 1/256 and offset 0
const QuantizationInfo allowed_quantization_info = QuantizationInfo(1.f / 256, 0);
@@ -396,16 +465,8 @@ void CLLogits1DNormKernel::configure(const ICLTensor *input, const ICLTensor *su
auto_init_if_empty(*output->info(),
input->info()->clone()->set_data_type(output_data_type).set_quantization_info(allowed_quantization_info));
- ARM_COMPUTE_ERROR_ON_MISMATCHING_SHAPES(input, output);
- if(!is_quantized_asymmetric)
- {
- ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
- ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, output);
- }
- else
- {
- ARM_COMPUTE_ERROR_ON(output->info()->quantization_info() != allowed_quantization_info);
- }
+ // Perform validation step
+ ARM_COMPUTE_ERROR_THROW_ON(CLLogits1DNormKernel::validate(input->info(), sum->info(), output->info()));
_input = input;
_sum = sum;
@@ -439,6 +500,36 @@ void CLLogits1DNormKernel::configure(const ICLTensor *input, const ICLTensor *su
ICLKernel::configure(win);
}
+Error CLLogits1DNormKernel::validate(const ITensorInfo *input, const ITensorInfo *sum, const ITensorInfo *output)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::S32, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(sum, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, sum);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, sum);
+
+ // Note: output should always have a scale of 1/256 and offset 0
+ const QuantizationInfo allowed_quantization_info = QuantizationInfo(1.f / 256, 0);
+ const bool is_quantized_asymmetric = (input->data_type() == DataType::S32);
+
+ // Checks performed when output is configured
+ if(output->total_size() != 0)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(input, output);
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT_POSITION(input, output);
+ if(!is_quantized_asymmetric)
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
+ }
+ else
+ {
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output, 1, DataType::QASYMM8);
+ ARM_COMPUTE_RETURN_ERROR_ON(output->quantization_info() != allowed_quantization_info);
+ }
+ }
+
+ return Error{};
+}
+
void CLLogits1DNormKernel::run(const Window &window, cl::CommandQueue &queue)
{
ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
diff --git a/src/core/TensorInfo.cpp b/src/core/TensorInfo.cpp
index a49b7b7e02..60e76bf84a 100644
--- a/src/core/TensorInfo.cpp
+++ b/src/core/TensorInfo.cpp
@@ -52,6 +52,7 @@ TensorInfo::TensorInfo(const ITensorInfo &info)
_is_resizable = info.is_resizable();
_valid_region = info.valid_region();
_padding = info.padding();
+ _quantization_info = info.quantization_info();
}
TensorInfo::TensorInfo(Format format)
@@ -387,6 +388,16 @@ ITensorInfo &TensorInfo::set_quantization_info(QuantizationInfo quantization_inf
return *this;
}
+ITensorInfo &TensorInfo::reset_padding()
+{
+ _padding = PaddingSize();
+ if(((_format != Format::UNKNOWN) || (_data_type != DataType::UNKNOWN)) && _total_size != 0)
+ {
+ std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
+ }
+ return *this;
+}
+
size_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
{
ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
diff --git a/src/runtime/CL/functions/CLDirectConvolutionLayer.cpp b/src/runtime/CL/functions/CLDirectConvolutionLayer.cpp
index 6fafd9c7f1..8ef7068b88 100644
--- a/src/runtime/CL/functions/CLDirectConvolutionLayer.cpp
+++ b/src/runtime/CL/functions/CLDirectConvolutionLayer.cpp
@@ -48,6 +48,11 @@ void CLDirectConvolutionLayer::configure(ICLTensor *input, const ICLTensor *weig
_input_border_handler.configure(input, _direct_conv_kernel.border_size(), BorderMode::CONSTANT, PixelValue(0));
}
+Error CLDirectConvolutionLayer::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info)
+{
+ return CLDirectConvolutionLayerKernel::validate(input, weights, biases, output, conv_info);
+}
+
void CLDirectConvolutionLayer::run()
{
// Run border handler
diff --git a/src/runtime/CL/functions/CLNormalizationLayer.cpp b/src/runtime/CL/functions/CLNormalizationLayer.cpp
index 648ce6b3a6..eefdec4ba4 100644
--- a/src/runtime/CL/functions/CLNormalizationLayer.cpp
+++ b/src/runtime/CL/functions/CLNormalizationLayer.cpp
@@ -48,6 +48,11 @@ void CLNormalizationLayer::configure(ICLTensor *input, ICLTensor *output, const
_border_handler.configure(input, _norm_kernel.border_size(), BorderMode::CONSTANT, PixelValue(0));
}
+Error CLNormalizationLayer::validate(const ITensorInfo *input, const ITensorInfo *output, const NormalizationLayerInfo &norm_info)
+{
+ return CLNormalizationLayerKernel::validate(input, output, norm_info);
+}
+
void CLNormalizationLayer::run()
{
// Run border handler
diff --git a/src/runtime/CL/functions/CLSoftmaxLayer.cpp b/src/runtime/CL/functions/CLSoftmaxLayer.cpp
index ff018d595c..d39335b6e5 100644
--- a/src/runtime/CL/functions/CLSoftmaxLayer.cpp
+++ b/src/runtime/CL/functions/CLSoftmaxLayer.cpp
@@ -45,16 +45,13 @@ void CLSoftmaxLayer::configure(const ICLTensor *input, ICLTensor *output, float
// Create intermediate tensors shapes
DataType tmp_data_type = is_data_type_quantized_asymmetric(input->info()->data_type()) ? DataType::S32 : input->info()->data_type();
- TensorInfo tensor_info_tmp(input->info()->tensor_shape(), input->info()->num_channels(), tmp_data_type, input->info()->fixed_point_position());
- tensor_info_tmp.set_quantization_info(input->info()->quantization_info());
+ TensorInfo tensor_info_tmp(input->info()->clone()->set_data_type(tmp_data_type).reset_padding());
_tmp.allocator()->init(tensor_info_tmp);
TensorShape max_sum_shape = input->info()->tensor_shape();
max_sum_shape.set(0, 1);
- TensorInfo tensor_info_max(max_sum_shape, input->info()->num_channels(), input->info()->data_type(), input->info()->fixed_point_position());
- tensor_info_max.set_quantization_info(input->info()->quantization_info());
- _max.allocator()->init(tensor_info_max);
- _sum.allocator()->init(TensorInfo(max_sum_shape, input->info()->num_channels(), tmp_data_type, input->info()->fixed_point_position()));
+ _max.allocator()->init(input->info()->clone()->set_tensor_shape(max_sum_shape).reset_padding());
+ _sum.allocator()->init(input->info()->clone()->set_tensor_shape(max_sum_shape).set_data_type(tmp_data_type).reset_padding());
// Set GPU target to kernels
_max_shift_exp_sum_kernel.set_target(CLScheduler::get().target());
@@ -84,6 +81,34 @@ void CLSoftmaxLayer::configure(const ICLTensor *input, ICLTensor *output, float
_sum.allocator()->allocate();
}
+Error CLSoftmaxLayer::validate(const ITensorInfo *input, const ITensorInfo *output)
+{
+ ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input);
+
+ // Create intermediate tensor info
+ DataType tmp_data_type = is_data_type_quantized_asymmetric(input->data_type()) ? DataType::S32 : input->data_type();
+ TensorInfo tensor_info_tmp(input->clone()->set_data_type(tmp_data_type));
+
+ TensorShape max_sum_shape = input->tensor_shape();
+ max_sum_shape.set(0, 1);
+ TensorInfo tensor_info_max(input->clone()->set_tensor_shape(max_sum_shape));
+ TensorInfo tensor_info_sum(input->clone()->set_tensor_shape(max_sum_shape).set_data_type(tmp_data_type).set_quantization_info(QuantizationInfo()));
+
+ bool run_legacy_path = is_data_type_quantized_asymmetric(input->data_type());
+ if(run_legacy_path)
+ {
+ ARM_COMPUTE_RETURN_ON_ERROR(CLLogits1DMaxKernel::validate(input, &tensor_info_max));
+ ARM_COMPUTE_RETURN_ON_ERROR(CLLogits1DShiftExpSumKernel::validate(input, &tensor_info_max, &tensor_info_tmp, &tensor_info_sum));
+ }
+ else
+ {
+ ARM_COMPUTE_RETURN_ON_ERROR(CLLogits1DMaxShiftExpSumKernel::validate(input, &tensor_info_max, &tensor_info_tmp, &tensor_info_sum));
+ }
+ ARM_COMPUTE_RETURN_ON_ERROR(CLLogits1DNormKernel::validate(&tensor_info_tmp, &tensor_info_sum, output));
+
+ return Error{};
+}
+
void CLSoftmaxLayer::run()
{
_memory_group.acquire();
diff --git a/tests/validation/CL/DirectConvolutionLayer.cpp b/tests/validation/CL/DirectConvolutionLayer.cpp
index 2986369d9b..08d53d5af3 100644
--- a/tests/validation/CL/DirectConvolutionLayer.cpp
+++ b/tests/validation/CL/DirectConvolutionLayer.cpp
@@ -79,6 +79,73 @@ TEST_SUITE(DirectConvolutionLayer)
//TODO(COMPMID-415): Configuration tests?
+// *INDENT-OFF*
+// clang-format off
+DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(
+ framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Mismatching data type input/weights
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Mismatching input feature maps
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Unsupported kernel width
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Non-rectangular weights dimensions
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Invalid weights dimensions
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Invalid stride
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Invalid biases size
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Invalid biases dimensions
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Invalid output size
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ }),
+ framework::dataset::make("WeightsInfo",{ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F16, 0),
+ TensorInfo(TensorShape(3U, 3U, 3U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(9U, 9U, 2U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(5U, 3U, 2U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(3U, 3U, 2U, 4U, 3U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32, 0),
+ })),
+ framework::dataset::make("BiasesInfo",{ TensorInfo(TensorShape(4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(3U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(4U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(4U), 1, DataType::F32, 0),
+ })),
+ framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(26U, 11U, 4U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, 0),
+ })),
+ framework::dataset::make("ConvInfo", { PadStrideInfo(1, 1, 0, 0),
+ PadStrideInfo(1, 1, 0, 0),
+ PadStrideInfo(1, 1, 0, 0),
+ PadStrideInfo(1, 1, 0, 0),
+ PadStrideInfo(1, 1, 0, 0),
+ PadStrideInfo(3, 3, 0, 0),
+ PadStrideInfo(1, 1, 0, 0),
+ PadStrideInfo(1, 1, 0, 0),
+ PadStrideInfo(1, 1, 0, 0),
+ PadStrideInfo(1, 1, 0, 0),
+ })),
+ framework::dataset::make("Expected", { true, true, true, true, true, true, true, true, true, false })),
+ input_info, weights_info, biases_info, output_info, conv_info, expected)
+{
+ bool is_error = bool(CLDirectConvolutionLayer::validate(&input_info, &weights_info, &biases_info, &output_info, conv_info));
+ ARM_COMPUTE_EXPECT(is_error == expected, framework::LogLevel::ERRORS);
+}
+// clang-format on
+// *INDENT-ON*
+
template <typename T>
using CLDirectConvolutionLayerFixture = DirectConvolutionValidationFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T>;
diff --git a/tests/validation/CL/NormalizationLayer.cpp b/tests/validation/CL/NormalizationLayer.cpp
index 18f0c37ab6..caf7e2a753 100644
--- a/tests/validation/CL/NormalizationLayer.cpp
+++ b/tests/validation/CL/NormalizationLayer.cpp
@@ -67,6 +67,38 @@ TEST_SUITE(NormalizationLayer)
//TODO(COMPMID-415): Missing configuration?
+// *INDENT-OFF*
+// clang-format off
+DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(
+ framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Mismatching data type input/output
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Mismatching shapes
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Even normalization
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0), // Non implemented IN_MAP_2D
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QS8, 4), // Mismatching fixed point position
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ }),
+ framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F16, 0),
+ TensorInfo(TensorShape(27U, 11U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QS8, 3),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, 0),
+ })),
+ framework::dataset::make("NormInfo", { NormalizationLayerInfo(NormType::IN_MAP_1D, 5),
+ NormalizationLayerInfo(NormType::IN_MAP_1D, 5),
+ NormalizationLayerInfo(NormType::IN_MAP_1D, 4),
+ NormalizationLayerInfo(NormType::IN_MAP_2D, 5),
+ NormalizationLayerInfo(NormType::IN_MAP_1D, 5),
+ NormalizationLayerInfo(NormType::IN_MAP_1D, 5),
+ })),
+ framework::dataset::make("Expected", { true, true, true, true, true, false })),
+ input_info, output_info, norm_info, expected)
+{
+ ARM_COMPUTE_EXPECT(bool(CLNormalizationLayer::validate(&input_info, &output_info, norm_info)) == expected, framework::LogLevel::ERRORS);
+}
+// clang-format on
+// *INDENT-ON*
+
template <typename T>
using CLNormalizationLayerFixture = NormalizationValidationFixture<CLTensor, CLAccessor, CLNormalizationLayer, T>;
diff --git a/tests/validation/CL/SoftmaxLayer.cpp b/tests/validation/CL/SoftmaxLayer.cpp
index a06aa7bbca..b935ef55a0 100644
--- a/tests/validation/CL/SoftmaxLayer.cpp
+++ b/tests/validation/CL/SoftmaxLayer.cpp
@@ -110,6 +110,37 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datase
validate(dst.info()->padding(), padding_dst);
}
+// *INDENT-OFF*
+// clang-format off
+DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(
+ framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching data types
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching shapes
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QS8, 2), // Mismatching fixed point
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QASYMM8, // Invalid output quantization info
+ QuantizationInfo(1.f/256, 12)),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QS8, 3),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QASYMM8,
+ QuantizationInfo(1.f/256, 12)),
+ }),
+ framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F16),
+ TensorInfo(TensorShape(27U, 11U, 2U), 1, DataType::F32),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QS8, 3),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QASYMM8,
+ QuantizationInfo(1.f/256, 12)),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QS8, 3),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QASYMM8,
+ QuantizationInfo(1.f/256, 0)),
+ })),
+ framework::dataset::make("Expected", { true, true, true, true, false, false, false })),
+ input_info, output_info, expected)
+{
+ ARM_COMPUTE_EXPECT(bool(CLSoftmaxLayer::validate(&input_info, &output_info)) == expected, framework::LogLevel::ERRORS);
+}
+// clang-format on
+// *INDENT-ON*
+
template <typename T>
using CLSoftmaxLayerFixture = SoftmaxValidationFixture<CLTensor, CLAccessor, CLSoftmaxLayer, T>;