From 0d0028ca25a47dd51260e2555b336fc9f09d1df1 Mon Sep 17 00:00:00 2001 From: Manuel Bottini Date: Tue, 2 Oct 2018 16:41:52 +0100 Subject: COMPMID-1298: Fuse ReLu activation in CLWinogradOutputTransform Change-Id: I9e6e43a5839d04c2e4b4552c05446efb0a5074cf Reviewed-on: https://review.mlplatform.org/232 Tested-by: Arm Jenkins Reviewed-by: Georgios Pinitas --- .../CL/kernels/CLWinogradOutputTransformKernel.h | 7 +- .../CL/functions/CLWinogradConvolutionLayer.h | 4 +- src/core/CL/cl_kernels/activation_helpers.h | 2 +- src/core/CL/cl_kernels/helpers.h | 3 + .../CL/cl_kernels/winograd_output_transform.cl | 203 +++++++++++++-------- .../CL/kernels/CLWinogradOutputTransformKernel.cpp | 35 +++- .../CL/functions/CLWinogradConvolutionLayer.cpp | 18 +- tests/validation/CL/Winograd.cpp | 99 ++++++---- .../fixtures/WinogradConvolutionLayerFixture.h | 16 +- 9 files changed, 241 insertions(+), 146 deletions(-) diff --git a/arm_compute/core/CL/kernels/CLWinogradOutputTransformKernel.h b/arm_compute/core/CL/kernels/CLWinogradOutputTransformKernel.h index 3bbbb5834c..bdb230d645 100644 --- a/arm_compute/core/CL/kernels/CLWinogradOutputTransformKernel.h +++ b/arm_compute/core/CL/kernels/CLWinogradOutputTransformKernel.h @@ -63,8 +63,10 @@ public: * @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 The output tensor. The shape for this tensor can be calculated using the utility function @p compute_winograd_output_transform_shape. Data types supported: Same as @p input * @param[in] winograd_info Contains Winograd's information described in @ref WinogradInfo + * @param[in] act_info (Optional) Activation layer information in case of a fused activation. */ - void configure(const ICLTensor *input, const ICLTensor *bias, ICLTensor *output, const WinogradInfo &winograd_info); + void configure(const ICLTensor *input, const ICLTensor *bias, ICLTensor *output, const WinogradInfo &winograd_info, const ActivationLayerInfo &act_info = ActivationLayerInfo()); + /** Static function to check if given info will lead to a valid configuration of @ref CLWinogradOutputTransformKernel * * @note Winograd output transform supports the following configurations for NCWH data layout @@ -82,10 +84,11 @@ public: * @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 The output tensor. The shape for this tensor can be calculated using the utility function @p compute_winograd_output_transform_shape. Data types supported: Same as @p input * @param[in] winograd_info Contains Winograd's information described in @ref WinogradInfo + * @param[in] act_info (Optional) Activation layer information in case of a fused activation @ref ActivationLayerInfo. Only RELU, BOUNDED_RELU, LU_BOUNDED_RELU, LEAKY_RELU and SOFT_RELU supported. * * @return a status */ - static Status validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const WinogradInfo &winograd_info); + static Status validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const WinogradInfo &winograd_info, const ActivationLayerInfo &act_info = ActivationLayerInfo()); // Inherited methods overridden: void run(const Window &window, cl::CommandQueue &queue) override; diff --git a/arm_compute/runtime/CL/functions/CLWinogradConvolutionLayer.h b/arm_compute/runtime/CL/functions/CLWinogradConvolutionLayer.h index 395f59500b..f11eb2a335 100644 --- a/arm_compute/runtime/CL/functions/CLWinogradConvolutionLayer.h +++ b/arm_compute/runtime/CL/functions/CLWinogradConvolutionLayer.h @@ -108,13 +108,11 @@ private: CLWinogradInputTransform _input_transform; CLWinogradFilterTransformKernel _filter_transform; CLWinogradOutputTransformKernel _output_transform; - CLActivationLayer _activationlayer_function; CLTensor _input0; CLTensor _input1; CLTensor _batched_mm_output; const ICLTensor *_original_weights; bool _is_prepared; - bool _is_activationlayer_enabled; }; -} +} // namespace arm_compute #endif /* __ARM_COMPUTE_CLWINOGRADCONVOLUTIONLAYER_H__ */ diff --git a/src/core/CL/cl_kernels/activation_helpers.h b/src/core/CL/cl_kernels/activation_helpers.h index dfab082381..9d4af8497a 100644 --- a/src/core/CL/cl_kernels/activation_helpers.h +++ b/src/core/CL/cl_kernels/activation_helpers.h @@ -70,7 +70,7 @@ inline TYPE lrelu_op(TYPE x) // Soft RELU Activation inline TYPE srelu_op(TYPE x) { - return LOG_OP(ADD_OP((TYPE)CONST_ONE, EXP_OP(x))); + return CONVERT(LOG_OP(ADD_OP((VEC_DATA_TYPE(float, VEC_SIZE))CONST_ONE, EXP_OP(CONVERT(x, VEC_DATA_TYPE(float, VEC_SIZE))))), TYPE); } // Absolute Activation inline TYPE abs_op(TYPE x) diff --git a/src/core/CL/cl_kernels/helpers.h b/src/core/CL/cl_kernels/helpers.h index 7ee97d9bbc..180bd50528 100644 --- a/src/core/CL/cl_kernels/helpers.h +++ b/src/core/CL/cl_kernels/helpers.h @@ -50,6 +50,9 @@ #define VSTORE_STR(size) vstore##size #define VSTORE(size) VSTORE_STR(size) +#define float1 float +#define half1 half + #define VEC_DATA_TYPE_STR(type, size) type##size #define VEC_DATA_TYPE(type, size) VEC_DATA_TYPE_STR(type, size) diff --git a/src/core/CL/cl_kernels/winograd_output_transform.cl b/src/core/CL/cl_kernels/winograd_output_transform.cl index f52b027420..e979978fa2 100644 --- a/src/core/CL/cl_kernels/winograd_output_transform.cl +++ b/src/core/CL/cl_kernels/winograd_output_transform.cl @@ -23,7 +23,15 @@ */ #include "helpers.h" +#if defined(FUSED_ACTIVATION) +#include "activation_layer.cl" +#define ACTIVATION_FUNC(x) ACTIVATION_OP(FUSED_ACTIVATION, x) +#else /* defined(FUSED_ACTIVATION) */ +#define ACTIVATION_FUNC(x) (x) +#endif /* defined(FUSED_ACTIVATION) */ + #if defined(NUM_TILES_X) && defined(OUTPUT_TILE_W) && defined(OUTPUT_TILE_H) +#if defined(VEC_SIZE) && VEC_SIZE == 2 /** This OpenCL kernel performs Winograd output transform when the output tile is 2x2/2x1 or 1x2, the filter size 3x3/3x1 or 1x3 and the data layout is NCHW * * @note The number of tiles along the X direction must be passed at compile time using -DNUM_TILES_X: e.g. -DNUM_TILES_X=16 @@ -32,6 +40,10 @@ * @note If this kernel is used to perform Winograd output transform 3x1, -DWINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL has to be passed at compile time * @note If this kernel is used to perform Winograd output transform 1x3, -DWINOGRAD_OUTPUT_TRANSFORM_VERTICAL has to be passed at compile time * @note The data type must be passed at compile time using -DDATA_TYPE e.g. -DDATA_TYPE=float. Supported data types: float/half. + * @note It is possible to select the activation function to apply using -DFUSED_ACTIVATION e.g. -DFUSED_ACTIVATION=relu + * @note A, B variables required by some activation functions are set using -DA_VAL= and -DB_VAL= respectively. + * @note Vector size should be given as a preprocessor argument using -DVEC_SIZE=size. Accepted values are -DVEC_SIZE=2 (for output_tile_size 2x2, 2x1, 1x2) and -DVEC_SIZE=4 (for output_tile_size 4x4, 4x1, 1x4) + * @note Select data type should be given too with -DSELECT_DATA_TYPE e.g -DSELECT_DATA_TYPE=int * * @param[in] src_ptr Pointer to the source tensor. Supported data types: F32/F16 * @param[in] src_stride_x Stride of the source tensor in X dimension (in bytes) @@ -86,6 +98,7 @@ __kernel void winograd_output_transform_2x2_3x3_nchw( float out00 = d00 + d01 + d02; float out01 = d01 - d02 - d03; #else // defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) || defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) + DATA_TYPE d10 = *((__global DATA_TYPE *)(src_addr + 4 * src_stride_z)); DATA_TYPE d11 = *((__global DATA_TYPE *)(src_addr + 5 * src_stride_z)); DATA_TYPE d12 = *((__global DATA_TYPE *)(src_addr + 6 * src_stride_z)); @@ -150,10 +163,12 @@ __kernel void winograd_output_transform_2x2_3x3_nchw( // Store the output tile #if defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) - *((__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)) = (DATA_TYPE)out00; - *((__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)) = (DATA_TYPE)out01; + const const VEC_DATA_TYPE(DATA_TYPE, 2) + out0_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 2))(out00, out01), VEC_DATA_TYPE(DATA_TYPE, 2))); + *((__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)) = out0_dt.s0; + *((__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)) = out0_dt.s1; #else // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) - vstore2((VEC_DATA_TYPE(DATA_TYPE, 2))(out00, out01), 0, (__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)); + vstore2(ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 2))(out00, out01), VEC_DATA_TYPE(DATA_TYPE, 2))), 0, (__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)); #endif // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) #if !defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) && !defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) @@ -162,11 +177,12 @@ __kernel void winograd_output_transform_2x2_3x3_nchw( out10 += (DATA_TYPE)b; out11 += (DATA_TYPE)b; #endif // defined(HAS_BIAS) - - vstore2((VEC_DATA_TYPE(DATA_TYPE, 2))((DATA_TYPE)out10, (DATA_TYPE)out11), 0, (__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)); + vstore2(ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 2))(out10, out11), VEC_DATA_TYPE(DATA_TYPE, 2))), 0, (__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)); #endif // !defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) && !defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) } +#endif // defined(VEC_SIZE) && VEC_SIZE == 2 +#if defined(VEC_SIZE) && VEC_SIZE == 4 /** This OpenCL kernel performs Winograd output transform when the output tile is 4x4, the filter size 3x3 and the data layout is NCHW * * @note The number of tiles along the X direction must be passed at compile time using -DNUM_TILES_X: e.g. -DNUM_TILES_X=16 @@ -230,6 +246,7 @@ __kernel void winograd_output_transform_4x4_3x3_nchw( float out02 = d01 + d02 + 4.0f * d03 + 4.0f * d04; float out03 = d01 - d02 + 8.0f * d03 - 8.0f * d04 + d05; #else // defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) || defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) + DATA_TYPE d10 = *((__global DATA_TYPE *)(src_addr + 6 * src_stride_z)); DATA_TYPE d11 = *((__global DATA_TYPE *)(src_addr + 7 * src_stride_z)); DATA_TYPE d12 = *((__global DATA_TYPE *)(src_addr + 8 * src_stride_z)); @@ -351,12 +368,14 @@ __kernel void winograd_output_transform_4x4_3x3_nchw( // Store the output tile #if defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) - *((__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)) = (DATA_TYPE)out00; - *((__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)) = (DATA_TYPE)out01; - *((__global DATA_TYPE *)(dst_addr + 2 * dst_stride_y)) = (DATA_TYPE)out02; - *((__global DATA_TYPE *)(dst_addr + 3 * dst_stride_y)) = (DATA_TYPE)out03; + VEC_DATA_TYPE(DATA_TYPE, 4) + out0_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))); + *((__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)) = out0_dt.s0; + *((__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)) = out0_dt.s1; + *((__global DATA_TYPE *)(dst_addr + 2 * dst_stride_y)) = out0_dt.s2; + *((__global DATA_TYPE *)(dst_addr + 3 * dst_stride_y)) = out0_dt.s3; #else // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))((DATA_TYPE)out00, (DATA_TYPE)out01, (DATA_TYPE)out02, (DATA_TYPE)out03), 0, (__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)); + vstore4(ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))), 0, (__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)); #endif // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) #if !defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) && !defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) @@ -377,9 +396,9 @@ __kernel void winograd_output_transform_4x4_3x3_nchw( out32 += (float)b; out33 += (float)b; #endif // defined(HAS_BIAS) - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))((DATA_TYPE)out10, (DATA_TYPE)out11, (DATA_TYPE)out12, (DATA_TYPE)out13), 0, (__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)); - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))((DATA_TYPE)out20, (DATA_TYPE)out21, (DATA_TYPE)out22, (DATA_TYPE)out23), 0, (__global DATA_TYPE *)(dst_addr + 2 * dst_stride_y)); - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))((DATA_TYPE)out30, (DATA_TYPE)out31, (DATA_TYPE)out32, (DATA_TYPE)out33), 0, (__global DATA_TYPE *)(dst_addr + 3 * dst_stride_y)); + vstore4(ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out10, out11, out12, out13), VEC_DATA_TYPE(DATA_TYPE, 4))), 0, (__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)); + vstore4(ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out20, out21, out22, out23), VEC_DATA_TYPE(DATA_TYPE, 4))), 0, (__global DATA_TYPE *)(dst_addr + 2 * dst_stride_y)); + vstore4(ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out30, out31, out32, out33), VEC_DATA_TYPE(DATA_TYPE, 4))), 0, (__global DATA_TYPE *)(dst_addr + 3 * dst_stride_y)); #endif // !defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) && !defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) } @@ -579,25 +598,29 @@ __kernel void winograd_output_transform_4x4_3x3_nhwc( #if defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) #if defined(SRC_DEPTH) int4 offset = (int4)(dst_offset_first_element_in_bytes + x_out * sizeof(DATA_TYPE) + y_out * dst_stride_y + z_out * dst_stride_z + batch * dst_stride_w); -#else /* defined(SRC_DEPTH) */ +#else /* defined(SRC_DEPTH) */ int4 offset = (int4)(dst_offset_first_element_in_bytes + x_out * sizeof(DATA_TYPE) + y_out * dst_stride_y + z_out * dst_stride_z); -#endif /* defined(SRC_DEPTH) */ +#endif /* defined(SRC_DEPTH) */ offset = min(offset + (int4)(0, 1, 2, 3) * (int4)dst_stride_z, (int4)dst_size); // If address is beyond the last plane, clamp it to dst_size (which points to the last padding). // Store the 1x4 output tile - *((__global DATA_TYPE *)(dst_ptr + offset.s0)) = (DATA_TYPE)out00; - *((__global DATA_TYPE *)(dst_ptr + offset.s1)) = (DATA_TYPE)out01; - *((__global DATA_TYPE *)(dst_ptr + offset.s2)) = (DATA_TYPE)out02; - *((__global DATA_TYPE *)(dst_ptr + offset.s3)) = (DATA_TYPE)out03; + VEC_DATA_TYPE(DATA_TYPE, 4) + out0_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))); + *((__global DATA_TYPE *)(dst_ptr + offset.s0)) = out0_dt.s0; + *((__global DATA_TYPE *)(dst_ptr + offset.s1)) = out0_dt.s1; + *((__global DATA_TYPE *)(dst_ptr + offset.s2)) = out0_dt.s2; + *((__global DATA_TYPE *)(dst_ptr + offset.s3)) = out0_dt.s3; #elif defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) // Store the 4x1 output tile int offset = dst_offset_first_element_in_bytes + x_out * sizeof(DATA_TYPE) + y_out * dst_stride_y + z_out * dst_stride_z; int mult_y = min(dst_size - offset, 1); - *((__global DATA_TYPE *)(dst_ptr + mult_y * 0 * dst_stride_y + offset)) = (DATA_TYPE)out00; - *((__global DATA_TYPE *)(dst_ptr + mult_y * 1 * dst_stride_y + offset)) = (DATA_TYPE)out01; - *((__global DATA_TYPE *)(dst_ptr + mult_y * 2 * dst_stride_y + offset)) = (DATA_TYPE)out02; - *((__global DATA_TYPE *)(dst_ptr + mult_y * 3 * dst_stride_y + offset)) = (DATA_TYPE)out03; + VEC_DATA_TYPE(DATA_TYPE, 4) + out0_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))); + *((__global DATA_TYPE *)(dst_ptr + mult_y * 0 * dst_stride_y + offset)) = out0_dt.s0; + *((__global DATA_TYPE *)(dst_ptr + mult_y * 1 * dst_stride_y + offset)) = out0_dt.s1; + *((__global DATA_TYPE *)(dst_ptr + mult_y * 2 * dst_stride_y + offset)) = out0_dt.s2; + *((__global DATA_TYPE *)(dst_ptr + mult_y * 3 * dst_stride_y + offset)) = out0_dt.s3; #else // defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) // Get output address #if defined(SRC_DEPTH) @@ -609,22 +632,30 @@ __kernel void winograd_output_transform_4x4_3x3_nhwc( int4 mult_y = min((int4)dst_size - offset, (int4)1); // If out of bound, we don't want to increase dst_stride_y, so we set the multiplier to 0. It will be 1 otherwise. // Store the 4x4 output tile - *((__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 0 * dst_stride_y + offset.s0)) = (DATA_TYPE)out00; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 1 * dst_stride_y + offset.s0)) = (DATA_TYPE)out01; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 2 * dst_stride_y + offset.s0)) = (DATA_TYPE)out02; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 3 * dst_stride_y + offset.s0)) = (DATA_TYPE)out03; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 0 * dst_stride_y + offset.s1)) = (DATA_TYPE)out10; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 1 * dst_stride_y + offset.s1)) = (DATA_TYPE)out11; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 2 * dst_stride_y + offset.s1)) = (DATA_TYPE)out12; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 3 * dst_stride_y + offset.s1)) = (DATA_TYPE)out13; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 0 * dst_stride_y + offset.s2)) = (DATA_TYPE)out20; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 1 * dst_stride_y + offset.s2)) = (DATA_TYPE)out21; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 2 * dst_stride_y + offset.s2)) = (DATA_TYPE)out22; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 3 * dst_stride_y + offset.s2)) = (DATA_TYPE)out23; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 0 * dst_stride_y + offset.s3)) = (DATA_TYPE)out30; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 1 * dst_stride_y + offset.s3)) = (DATA_TYPE)out31; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 2 * dst_stride_y + offset.s3)) = (DATA_TYPE)out32; - *((__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 3 * dst_stride_y + offset.s3)) = (DATA_TYPE)out33; + VEC_DATA_TYPE(DATA_TYPE, 4) + out0_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))); + VEC_DATA_TYPE(DATA_TYPE, 4) + out1_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out10, out11, out12, out13), VEC_DATA_TYPE(DATA_TYPE, 4))); + VEC_DATA_TYPE(DATA_TYPE, 4) + out2_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out20, out21, out22, out23), VEC_DATA_TYPE(DATA_TYPE, 4))); + VEC_DATA_TYPE(DATA_TYPE, 4) + out3_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out30, out31, out32, out33), VEC_DATA_TYPE(DATA_TYPE, 4))); + *((__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 0 * dst_stride_y + offset.s0)) = out0_dt.s0; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 1 * dst_stride_y + offset.s0)) = out0_dt.s1; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 2 * dst_stride_y + offset.s0)) = out0_dt.s2; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 3 * dst_stride_y + offset.s0)) = out0_dt.s3; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 0 * dst_stride_y + offset.s1)) = out1_dt.s0; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 1 * dst_stride_y + offset.s1)) = out1_dt.s1; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 2 * dst_stride_y + offset.s1)) = out1_dt.s2; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 3 * dst_stride_y + offset.s1)) = out1_dt.s3; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 0 * dst_stride_y + offset.s2)) = out2_dt.s0; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 1 * dst_stride_y + offset.s2)) = out2_dt.s1; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 2 * dst_stride_y + offset.s2)) = out2_dt.s2; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 3 * dst_stride_y + offset.s2)) = out2_dt.s3; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 0 * dst_stride_y + offset.s3)) = out3_dt.s0; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 1 * dst_stride_y + offset.s3)) = out3_dt.s1; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 2 * dst_stride_y + offset.s3)) = out3_dt.s2; + *((__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 3 * dst_stride_y + offset.s3)) = out3_dt.s3; #endif // defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) } @@ -690,6 +721,7 @@ __kernel void winograd_output_transform_4x4_5x5_nchw( Tensor4D src = CONVERT_TO_TENSOR4D_STRUCT(src, SRC_DEPTH); const __global uchar *src_addr = tensor4D_offset(&src, 0, 0, 0, 0); #else /* defined(SRC_DEPTH) */ + Tensor3D src = CONVERT_TO_TENSOR3D_STRUCT(src); const __global uchar *src_addr = tensor3D_offset(&src, 0, 0, 0); #endif /* defined(SRC_DEPTH) */ @@ -706,6 +738,7 @@ __kernel void winograd_output_transform_4x4_5x5_nchw( #if defined(SRC_DEPTH) __global uchar *dst_addr = dst_ptr + dst_offset_first_element_in_bytes + x_out * sizeof(DATA_TYPE) + y_out * dst_stride_y + z_out * dst_stride_z + batch * dst_stride_w; #else /* defined(SRC_DEPTH) */ + __global uchar *dst_addr = dst_ptr + dst_offset_first_element_in_bytes + x_out * sizeof(DATA_TYPE) + y_out * dst_stride_y + z_out * dst_stride_z; #endif /* defined(SRC_DEPTH) */ @@ -740,15 +773,18 @@ __kernel void winograd_output_transform_4x4_5x5_nchw( // Store the output tile #if defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) - *((__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)) = out00; - *((__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)) = out01; - *((__global DATA_TYPE *)(dst_addr + 2 * dst_stride_y)) = out02; - *((__global DATA_TYPE *)(dst_addr + 3 * dst_stride_y)) = out03; + VEC_DATA_TYPE(DATA_TYPE, 4) + out0_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))); + *((__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)) = out0_dt.s0; + *((__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)) = out0_dt.s1; + *((__global DATA_TYPE *)(dst_addr + 2 * dst_stride_y)) = out0_dt.s2; + *((__global DATA_TYPE *)(dst_addr + 3 * dst_stride_y)) = out0_dt.s3; #else // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))(out00, out01, out02, out03), 0, (__global DATA_TYPE *)(dst_addr)); + vstore4(ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))), 0, (__global DATA_TYPE *)(dst_addr)); #endif // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) #else // defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) || defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) + DATA_TYPE d10 = *((__global DATA_TYPE *)(src_addr + 8 * src_stride_z)); DATA_TYPE d11 = *((__global DATA_TYPE *)(src_addr + 9 * src_stride_z)); DATA_TYPE d12 = *((__global DATA_TYPE *)(src_addr + 10 * src_stride_z)); @@ -859,10 +895,10 @@ __kernel void winograd_output_transform_4x4_5x5_nchw( #endif // defined(HAS_BIAS) // Store the output tile - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))((DATA_TYPE)out_col0.s0, (DATA_TYPE)out_col1.s0, (DATA_TYPE)out_col2.s0, (DATA_TYPE)out_col3.s0), 0, (__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)); - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))((DATA_TYPE)out_col0.s1, (DATA_TYPE)out_col1.s1, (DATA_TYPE)out_col2.s1, (DATA_TYPE)out_col3.s1), 0, (__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)); - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))((DATA_TYPE)out_col0.s2, (DATA_TYPE)out_col1.s2, (DATA_TYPE)out_col2.s2, (DATA_TYPE)out_col3.s2), 0, (__global DATA_TYPE *)(dst_addr + 2 * dst_stride_y)); - vstore4((VEC_DATA_TYPE(DATA_TYPE, 4))((DATA_TYPE)out_col0.s3, (DATA_TYPE)out_col1.s3, (DATA_TYPE)out_col2.s3, (DATA_TYPE)out_col3.s3), 0, (__global DATA_TYPE *)(dst_addr + 3 * dst_stride_y)); + vstore4(ACTIVATION_FUNC((VEC_DATA_TYPE(DATA_TYPE, 4))(out_col0.s0, out_col1.s0, out_col2.s0, out_col3.s0)), 0, (__global DATA_TYPE *)(dst_addr + 0 * dst_stride_y)); + vstore4(ACTIVATION_FUNC((VEC_DATA_TYPE(DATA_TYPE, 4))(out_col0.s1, out_col1.s1, out_col2.s1, out_col3.s1)), 0, (__global DATA_TYPE *)(dst_addr + 1 * dst_stride_y)); + vstore4(ACTIVATION_FUNC((VEC_DATA_TYPE(DATA_TYPE, 4))(out_col0.s2, out_col1.s2, out_col2.s2, out_col3.s2)), 0, (__global DATA_TYPE *)(dst_addr + 2 * dst_stride_y)); + vstore4(ACTIVATION_FUNC((VEC_DATA_TYPE(DATA_TYPE, 4))(out_col0.s3, out_col1.s3, out_col2.s3, out_col3.s3)), 0, (__global DATA_TYPE *)(dst_addr + 3 * dst_stride_y)); #endif // !defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) && !defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) } @@ -960,18 +996,21 @@ __kernel void winograd_output_transform_4x4_5x5_nhwc( #endif /* defined(SRC_DEPTH) */ offset = min(offset + (int4)(0, 1, 2, 3) * (int4)dst_stride_z, (int4)dst_size); // If address is beyond the last plane, clamp it to dst_size (which points to the last padding). - *(__global DATA_TYPE *)(dst_ptr + offset.s0) = (DATA_TYPE)out00; - *(__global DATA_TYPE *)(dst_ptr + offset.s1) = (DATA_TYPE)out01; - *(__global DATA_TYPE *)(dst_ptr + offset.s2) = (DATA_TYPE)out02; - *(__global DATA_TYPE *)(dst_ptr + offset.s3) = (DATA_TYPE)out03; + VEC_DATA_TYPE(DATA_TYPE, 4) + out0_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))); + *(__global DATA_TYPE *)(dst_ptr + offset.s0) = out0_dt.s0; + *(__global DATA_TYPE *)(dst_ptr + offset.s1) = out0_dt.s1; + *(__global DATA_TYPE *)(dst_ptr + offset.s2) = out0_dt.s2; + *(__global DATA_TYPE *)(dst_ptr + offset.s3) = out0_dt.s3; #else // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) // Get output address int offset = dst_offset_first_element_in_bytes + x_out * sizeof(DATA_TYPE) + y_out * dst_stride_y + z_out * dst_stride_z; - - *(__global DATA_TYPE *)(dst_ptr + 0 * dst_stride_y + offset) = (DATA_TYPE)out00; - *(__global DATA_TYPE *)(dst_ptr + 1 * dst_stride_y + offset) = (DATA_TYPE)out01; - *(__global DATA_TYPE *)(dst_ptr + 2 * dst_stride_y + offset) = (DATA_TYPE)out02; - *(__global DATA_TYPE *)(dst_ptr + 3 * dst_stride_y + offset) = (DATA_TYPE)out03; + VEC_DATA_TYPE(DATA_TYPE, 4) + out0_dt = ACTIVATION_FUNC(CONVERT((VEC_DATA_TYPE(float, 4))(out00, out01, out02, out03), VEC_DATA_TYPE(DATA_TYPE, 4))); + *(__global DATA_TYPE *)(dst_ptr + 0 * dst_stride_y + offset) = out0_dt.s0; + *(__global DATA_TYPE *)(dst_ptr + 1 * dst_stride_y + offset) = out0_dt.s1; + *(__global DATA_TYPE *)(dst_ptr + 2 * dst_stride_y + offset) = out0_dt.s2; + *(__global DATA_TYPE *)(dst_ptr + 3 * dst_stride_y + offset) = out0_dt.s3; #endif // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) #else // defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) || defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) @@ -1094,26 +1133,37 @@ __kernel void winograd_output_transform_4x4_5x5_nhwc( int4 mult_y = min((int4)dst_size - offset, (int4)1); // If out of bound, we don't want to increase dst_stride_y, so we set the multiplier to 0. It will be 1 otherwise. // Store the output tile - *(__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 0 * (int)dst_stride_y + offset.s0) = (DATA_TYPE)out_col0.s0; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 1 * (int)dst_stride_y + offset.s0) = (DATA_TYPE)out_col1.s0; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 2 * (int)dst_stride_y + offset.s0) = (DATA_TYPE)out_col2.s0; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 3 * (int)dst_stride_y + offset.s0) = (DATA_TYPE)out_col3.s0; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 0 * (int)dst_stride_y + offset.s1) = (DATA_TYPE)out_col0.s1; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 1 * (int)dst_stride_y + offset.s1) = (DATA_TYPE)out_col1.s1; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 2 * (int)dst_stride_y + offset.s1) = (DATA_TYPE)out_col2.s1; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 3 * (int)dst_stride_y + offset.s1) = (DATA_TYPE)out_col3.s1; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 0 * (int)dst_stride_y + offset.s2) = (DATA_TYPE)out_col0.s2; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 1 * (int)dst_stride_y + offset.s2) = (DATA_TYPE)out_col1.s2; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 2 * (int)dst_stride_y + offset.s2) = (DATA_TYPE)out_col2.s2; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 3 * (int)dst_stride_y + offset.s2) = (DATA_TYPE)out_col3.s2; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 0 * (int)dst_stride_y + offset.s3) = (DATA_TYPE)out_col0.s3; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 1 * (int)dst_stride_y + offset.s3) = (DATA_TYPE)out_col1.s3; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 2 * (int)dst_stride_y + offset.s3) = (DATA_TYPE)out_col2.s3; - *(__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 3 * (int)dst_stride_y + offset.s3) = (DATA_TYPE)out_col3.s3; + VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE) + out_col0_dt = ACTIVATION_FUNC(CONVERT(out_col0, VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE))); + VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE) + out_col1_dt = ACTIVATION_FUNC(CONVERT(out_col1, VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE))); + VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE) + out_col2_dt = ACTIVATION_FUNC(CONVERT(out_col2, VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE))); + VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE) + out_col3_dt = ACTIVATION_FUNC(CONVERT(out_col3, VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE))); + + *(__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 0 * (int)dst_stride_y + offset.s0) = out_col0_dt.s0; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 1 * (int)dst_stride_y + offset.s0) = out_col1_dt.s0; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 2 * (int)dst_stride_y + offset.s0) = out_col2_dt.s0; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s0 * 3 * (int)dst_stride_y + offset.s0) = out_col3_dt.s0; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 0 * (int)dst_stride_y + offset.s1) = out_col0_dt.s1; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 1 * (int)dst_stride_y + offset.s1) = out_col1_dt.s1; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 2 * (int)dst_stride_y + offset.s1) = out_col2_dt.s1; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s1 * 3 * (int)dst_stride_y + offset.s1) = out_col3_dt.s1; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 0 * (int)dst_stride_y + offset.s2) = out_col0_dt.s2; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 1 * (int)dst_stride_y + offset.s2) = out_col1_dt.s2; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 2 * (int)dst_stride_y + offset.s2) = out_col2_dt.s2; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s2 * 3 * (int)dst_stride_y + offset.s2) = out_col3_dt.s2; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 0 * (int)dst_stride_y + offset.s3) = out_col0_dt.s3; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 1 * (int)dst_stride_y + offset.s3) = out_col1_dt.s3; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 2 * (int)dst_stride_y + offset.s3) = out_col2_dt.s3; + *(__global DATA_TYPE *)(dst_ptr + mult_y.s3 * 3 * (int)dst_stride_y + offset.s3) = out_col3_dt.s3; #endif // defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) || defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) } +#endif // defined(VEC_SIZE) && VEC_SIZE == 4 #if defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) +#if defined(VEC_SIZE) && VEC_SIZE == 2 /** This OpenCL kernel performs Winograd output transform when the output tile is 2x1, the filter size 3x1 and the data layout is NCHW * * @note The number of tiles along the X direction must be passed at compile time using -DNUM_TILES_X: e.g. -DNUM_TILES_X=16 @@ -1181,7 +1231,9 @@ __kernel void winograd_output_transform_2x1_3x1_nchw( #endif // defined(HAS_BIAS) ); } +#endif // defined(VEC_SIZE) && VEC_SIZE == 2 +#if defined(VEC_SIZE) && VEC_SIZE == 4 /** This OpenCL kernel performs Winograd output transform when the output tile is 4x1, the filter size 3x1 and the data layout is NCHW * * @note The number of tiles along the X direction must be passed at compile time using -DNUM_TILES_X: e.g. -DNUM_TILES_X=16 @@ -1449,9 +1501,11 @@ __kernel void winograd_output_transform_4x1_5x1_nhwc( #endif // defined(HAS_BIAS) dst_size); } +#endif // defined(VEC_SIZE) && VEC_SIZE == 4 #endif // defined(WINOGRAD_OUTPUT_TRANSFORM_HORIZONTAL) #if defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) +#if defined(VEC_SIZE) && VEC_SIZE == 2 /** This OpenCL kernel performs Winograd output transform when the output tile is 1x2, the filter size 1x3 and the data layout is NCHW * * @note The number of tiles along the X direction must be passed at compile time using -DNUM_TILES_X: e.g. -DNUM_TILES_X=16 @@ -1519,7 +1573,9 @@ __kernel void winograd_output_transform_1x2_1x3_nchw( #endif // defined(HAS_BIAS) ); } +#endif // defined(VEC_SIZE) && VEC_SIZE == 2 +#if defined(VEC_SIZE) && VEC_SIZE == 4 /** This OpenCL kernel performs Winograd output transform when the output tile is 1x4, the filter size 1x3 and the data layout is NCHW * * @note The number of tiles along the X direction must be passed at compile time using -DNUM_TILES_X: e.g. -DNUM_TILES_X=16 @@ -1787,5 +1843,6 @@ __kernel void winograd_output_transform_1x4_1x5_nhwc( #endif // defined(HAS_BIAS) dst_size); } +#endif // defined(VEC_SIZE) && VEC_SIZE == 4 #endif // defined(WINOGRAD_OUTPUT_TRANSFORM_VERTICAL) #endif // defined(NUM_TILES_X) && defined(OUTPUT_TILE_W) && defined(OUTPUT_TILE_H) diff --git a/src/core/CL/kernels/CLWinogradOutputTransformKernel.cpp b/src/core/CL/kernels/CLWinogradOutputTransformKernel.cpp index 7f1afe0058..84b5ea23f1 100644 --- a/src/core/CL/kernels/CLWinogradOutputTransformKernel.cpp +++ b/src/core/CL/kernels/CLWinogradOutputTransformKernel.cpp @@ -46,8 +46,18 @@ using namespace arm_compute::misc::shape_calculator; namespace { -Status validate_arguments(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const WinogradInfo &winograd_info) +Status validate_arguments(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const WinogradInfo &winograd_info, const ActivationLayerInfo &act_info) { + if(act_info.enabled()) + { + ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(input); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::U8, DataType::QASYMM8, DataType::F16, DataType::F32); + ARM_COMPUTE_RETURN_ERROR_ON_MSG((input->data_type() == DataType::QASYMM8) && (act_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU) + && (act_info.activation() != ActivationLayerInfo::ActivationFunction::BOUNDED_RELU) + && (act_info.activation() != ActivationLayerInfo::ActivationFunction::RELU) + && (act_info.activation() != ActivationLayerInfo::ActivationFunction::LOGISTIC), + "For QASYMM8 only logistic, relu, lower bounded relu and lower-upper bounded relu are supported"); + } ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F32, DataType::F16); ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(input); @@ -133,14 +143,14 @@ CLWinogradOutputTransformKernel::CLWinogradOutputTransformKernel() { } -void CLWinogradOutputTransformKernel::configure(const ICLTensor *input, const ICLTensor *bias, ICLTensor *output, const WinogradInfo &winograd_info) +void CLWinogradOutputTransformKernel::configure(const ICLTensor *input, const ICLTensor *bias, ICLTensor *output, const WinogradInfo &winograd_info, const ActivationLayerInfo &act_info) { ARM_COMPUTE_ERROR_ON_NULLPTR(input, output); // Output tensor auto initialization if not yet initialized auto_init_if_empty(*output->info(), input->info()->clone()->set_tensor_shape(compute_winograd_output_transform_shape(*input->info(), winograd_info))); - ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), (bias != nullptr ? bias->info() : nullptr), output->info(), winograd_info)); + ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), (bias != nullptr ? bias->info() : nullptr), output->info(), winograd_info, act_info)); _input = input; _bias = bias; @@ -161,6 +171,21 @@ void CLWinogradOutputTransformKernel::configure(const ICLTensor *input, const IC // Set build options CLBuildOptions build_opts; + build_opts.add_option_if(act_info.enabled(), "-DFUSED_ACTIVATION=" + lower_string(string_from_activation_func(act_info.activation()))); + build_opts.add_option_if(act_info.enabled(), "-DA_VAL=" + float_to_string_with_full_precision(act_info.a())); + build_opts.add_option_if(act_info.enabled(), "-DB_VAL=" + float_to_string_with_full_precision(act_info.b())); + + if((output_tile_size.x() == 2) || (output_tile_size.x() == 1 && output_tile_size.y() == 2)) + { + build_opts.add_option("-DVEC_SIZE=2"); + } + else if((output_tile_size.x() == 4) || (output_tile_size.x() == 1 && output_tile_size.y() == 4)) + { + build_opts.add_option("-DVEC_SIZE=4"); + } + + build_opts.add_option_if(act_info.enabled(), "-DSELECT_DATA_TYPE=" + get_cl_select_type_from_data_type(input->info()->data_type())); + build_opts.add_option_if(_bias != nullptr, std::string("-DHAS_BIAS")); build_opts.add_option("-DNUM_TILES_X=" + support::cpp11::to_string(num_tiles.width)); build_opts.add_option("-DOUTPUT_TILE_W=" + support::cpp11::to_string(output_tile_size.width)); @@ -195,9 +220,9 @@ void CLWinogradOutputTransformKernel::configure(const ICLTensor *input, const IC _config_id += lower_string(string_from_data_layout(winograd_info.output_data_layout)); } -Status CLWinogradOutputTransformKernel::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const WinogradInfo &winograd_info) +Status CLWinogradOutputTransformKernel::validate(const ITensorInfo *input, const ITensorInfo *bias, const ITensorInfo *output, const WinogradInfo &winograd_info, const ActivationLayerInfo &act_info) { - ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, (bias != nullptr ? bias->clone().get() : nullptr), output, winograd_info)); + ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, (bias != nullptr ? bias->clone().get() : nullptr), output, winograd_info, act_info)); ARM_COMPUTE_RETURN_ON_ERROR(validate_and_configure_window(input->clone().get(), (bias != nullptr ? bias->clone().get() : nullptr), output->clone().get(), winograd_info.output_tile_size).first); return Status{}; diff --git a/src/runtime/CL/functions/CLWinogradConvolutionLayer.cpp b/src/runtime/CL/functions/CLWinogradConvolutionLayer.cpp index 1abcb67132..069196e8c1 100644 --- a/src/runtime/CL/functions/CLWinogradConvolutionLayer.cpp +++ b/src/runtime/CL/functions/CLWinogradConvolutionLayer.cpp @@ -84,8 +84,8 @@ bool check_support_fast_math(const Size2D &output_tile, const Size2D &kernel_siz } // namespace CLWinogradConvolutionLayer::CLWinogradConvolutionLayer(std::shared_ptr memory_manager) - : _memory_group(memory_manager), _batched_mm(memory_manager), _input_transform(), _filter_transform(), _output_transform(), _activationlayer_function(), _input0(), _input1(), _batched_mm_output(), - _original_weights(nullptr), _is_prepared(false), _is_activationlayer_enabled(false) + : _memory_group(memory_manager), _batched_mm(memory_manager), _input_transform(), _filter_transform(), _output_transform(), _input0(), _input1(), _batched_mm_output(), _original_weights(nullptr), + _is_prepared(false) { } @@ -133,14 +133,7 @@ void CLWinogradConvolutionLayer::configure(ICLTensor *input, const ICLTensor *we (input->info()->data_type() == DataType::F16))); // Configure output transform - _output_transform.configure(&_batched_mm_output, biases, output, winograd_info); - - // Configure activation layer - _is_activationlayer_enabled = act_info.enabled(); - if(_is_activationlayer_enabled) - { - _activationlayer_function.configure(output, nullptr, act_info); - } + _output_transform.configure(&_batched_mm_output, biases, output, winograd_info, act_info); // Allocate temporary tensors _input0.allocator()->allocate(); @@ -216,11 +209,6 @@ void CLWinogradConvolutionLayer::run() // Run output transform CLScheduler::get().enqueue(_output_transform); - if(_is_activationlayer_enabled) - { - _activationlayer_function.run(); - } - _memory_group.release(); } diff --git a/tests/validation/CL/Winograd.cpp b/tests/validation/CL/Winograd.cpp index f7f06b7f79..efa049f5ab 100644 --- a/tests/validation/CL/Winograd.cpp +++ b/tests/validation/CL/Winograd.cpp @@ -139,6 +139,17 @@ const auto SmallWinogradOutputTransformDatasetNHWC = datasets::SmallWinogradOutp const auto LargeWinogradOutputTransformDatasetNCHW = datasets::LargeWinogradOutputTransformDatasetNCHW(); const auto LargeWinogradOutputTransformDatasetNHWC = datasets::LargeWinogradOutputTransformDatasetNHWC(); + +//Activation Functions +const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo", +{ + ActivationLayerInfo(), + ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU), + ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU), + ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU), + ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LEAKY_RELU), + ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::SOFT_RELU) +}); } // namespace using namespace arm_compute::misc::shape_calculator; @@ -562,16 +573,18 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(framework::da } TEST_SUITE(FP16) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradOutputTransformFixtureFP16, framework::DatasetMode::ALL, - combine(SmallWinogradOutputTransformDatasetNCHW, - framework::dataset::make("DataType", { DataType::F16 }))) + combine(combine(SmallWinogradOutputTransformDatasetNCHW, + framework::dataset::make("DataType", { DataType::F16 })), + framework::dataset::make("ActivationInfo",{ ActivationLayerInfo() }) )) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); } FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradOutputTransformFixtureFP16, framework::DatasetMode::NIGHTLY, - combine(LargeWinogradOutputTransformDatasetNCHW, - framework::dataset::make("DataType", { DataType::F16 }))) + combine(combine(LargeWinogradOutputTransformDatasetNCHW, + framework::dataset::make("DataType", { DataType::F16 })), + framework::dataset::make("ActivationInfo",{ ActivationLayerInfo() }) )) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); @@ -579,16 +592,18 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradOutputTransformFixtureFP16, framework TEST_SUITE_END() // FP16 TEST_SUITE(FP32) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradOutputTransformFixtureFP32, framework::DatasetMode::ALL, - combine(SmallWinogradOutputTransformDatasetNCHW, - framework::dataset::make("DataType", { DataType::F32 }))) + combine(combine(SmallWinogradOutputTransformDatasetNCHW, + framework::dataset::make("DataType", { DataType::F32 })), + framework::dataset::make("ActivationInfo",{ ActivationLayerInfo() }) )) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f32); } FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradOutputTransformFixtureFP32, framework::DatasetMode::NIGHTLY, - combine(LargeWinogradOutputTransformDatasetNCHW, - framework::dataset::make("DataType", { DataType::F32 }))) + combine(combine(LargeWinogradOutputTransformDatasetNCHW, + framework::dataset::make("DataType", { DataType::F32 })), + framework::dataset::make("ActivationInfo",{ ActivationLayerInfo() }) )) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f32); @@ -618,16 +633,18 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(framework::da TEST_SUITE(FP16) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradOutputTransformFixtureFP16, framework::DatasetMode::ALL, - combine(SmallWinogradOutputTransformDatasetNHWC, - framework::dataset::make("DataType", { DataType::F16 }))) + combine(combine(SmallWinogradOutputTransformDatasetNHWC, + framework::dataset::make("DataType", { DataType::F16 })), + framework::dataset::make("ActivationInfo",{ ActivationLayerInfo() }) )) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); } FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradOutputTransformFixtureFP16, framework::DatasetMode::NIGHTLY, - combine(LargeWinogradOutputTransformDatasetNHWC, - framework::dataset::make("DataType", { DataType::F16 }))) + combine(combine(LargeWinogradOutputTransformDatasetNHWC, + framework::dataset::make("DataType", { DataType::F16 })), + framework::dataset::make("ActivationInfo",{ ActivationLayerInfo() }) )) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); @@ -635,16 +652,18 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradOutputTransformFixtureFP16, framework TEST_SUITE_END() // FP16 TEST_SUITE(FP32) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradOutputTransformFixtureFP32, framework::DatasetMode::ALL, - combine(SmallWinogradOutputTransformDatasetNHWC, - framework::dataset::make("DataType", { DataType::F32 }))) + combine(combine(SmallWinogradOutputTransformDatasetNHWC, + framework::dataset::make("DataType", { DataType::F32 })), + framework::dataset::make("ActivationInfo",{ ActivationLayerInfo() }) )) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f32); } FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradOutputTransformFixtureFP32, framework::DatasetMode::NIGHTLY, - combine(LargeWinogradOutputTransformDatasetNHWC, - framework::dataset::make("DataType", { DataType::F32 }))) + combine(combine(LargeWinogradOutputTransformDatasetNHWC, + framework::dataset::make("DataType", { DataType::F32 })), + framework::dataset::make("ActivationInfo",{ ActivationLayerInfo() }) )) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f32); @@ -702,7 +721,7 @@ TEST_SUITE(Conv3x3) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x3Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -712,7 +731,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, fram FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x3Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -724,7 +743,7 @@ TEST_SUITE(Conv3x1) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x1Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -734,7 +753,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, fram FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x1Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -746,7 +765,7 @@ TEST_SUITE(Conv1x3) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x3Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -756,7 +775,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, fram FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer1x3Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -768,7 +787,7 @@ TEST_SUITE(Conv5x5) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer5x5Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset ), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -779,7 +798,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, fram FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer5x5Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset ), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -792,7 +811,7 @@ TEST_SUITE(Conv5x1) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer5x1Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -803,7 +822,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, fram FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer5x1Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -816,7 +835,7 @@ TEST_SUITE(Conv1x5) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x5Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -827,7 +846,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture, fram FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer1x5Dataset(), framework::dataset::make("DataType", { DataType::F32 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -845,7 +864,7 @@ TEST_SUITE(Conv3x3) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x3Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -855,7 +874,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, fr FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x3Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -867,7 +886,7 @@ TEST_SUITE(Conv3x1) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x1Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -877,7 +896,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, fr FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x1Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -889,7 +908,7 @@ TEST_SUITE(Conv1x3) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x3Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -899,7 +918,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, fr FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer1x3Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { // Validate output @@ -911,7 +930,7 @@ TEST_SUITE(Conv5x5) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer5x5Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -922,7 +941,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, fr FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer5x5Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -935,7 +954,7 @@ TEST_SUITE(Conv5x1) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer5x1Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -946,7 +965,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, fr FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer5x1Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -959,7 +978,7 @@ TEST_SUITE(Conv1x5) FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x5Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { @@ -970,7 +989,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, fr FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeWinogradConvolutionLayer1x5Dataset(), framework::dataset::make("DataType", { DataType::F16 })), - framework::dataset::make("ActivationLayerInfo", { ActivationLayerInfo() })), + ActivationFunctionsDataset), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }))) { diff --git a/tests/validation/fixtures/WinogradConvolutionLayerFixture.h b/tests/validation/fixtures/WinogradConvolutionLayerFixture.h index 9c9e634205..8f34654c3a 100644 --- a/tests/validation/fixtures/WinogradConvolutionLayerFixture.h +++ b/tests/validation/fixtures/WinogradConvolutionLayerFixture.h @@ -494,10 +494,10 @@ class WinogradOutputTransformValidationFixture : public framework::Fixture { public: template - void setup(TensorShape input_shape, WinogradInfo winograd_info, DataType data_type) + void setup(TensorShape input_shape, WinogradInfo winograd_info, DataType data_type, ActivationLayerInfo act_info = ActivationLayerInfo()) { - _target = compute_target(input_shape, winograd_info, data_type); - _reference = compute_reference(input_shape, winograd_info, data_type); + _target = compute_target(input_shape, winograd_info, data_type, act_info); + _reference = compute_reference(input_shape, winograd_info, data_type, act_info); } protected: @@ -522,7 +522,7 @@ protected: } } - TensorType compute_target(const TensorShape &input_shape, const WinogradInfo &winograd_info, DataType data_type) + TensorType compute_target(const TensorShape &input_shape, const WinogradInfo &winograd_info, DataType data_type, ActivationLayerInfo act_info) { TensorShape output_shape = compute_winograd_output_transform_shape(TensorInfo(input_shape, 1, data_type), winograd_info); @@ -533,7 +533,7 @@ protected: // Create and configure function FunctionType output_transform; - output_transform.configure(&src, &bias, &dst, winograd_info); + output_transform.configure(&src, &bias, &dst, winograd_info, act_info); ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS); @@ -557,7 +557,7 @@ protected: return dst; } - SimpleTensor compute_reference(const TensorShape &input_shape, WinogradInfo winograd_info, DataType data_type) + SimpleTensor compute_reference(const TensorShape &input_shape, WinogradInfo winograd_info, DataType data_type, ActivationLayerInfo act_info) { winograd_info.output_data_layout = DataLayout::NCHW; TensorShape output_shape = compute_winograd_output_transform_shape(TensorInfo(input_shape, 1, data_type), winograd_info); @@ -570,7 +570,9 @@ protected: fill(src, 0, -1.f, 1.f); fill(bias, 1, -1.f, 1.f); - return reference::winograd_output_transform(src, bias, output_shape, winograd_info); + const SimpleTensor winograd_output = reference::winograd_output_transform(src, bias, output_shape, winograd_info); + + return (act_info.enabled()) ? reference::activation_layer(winograd_output, act_info) : winograd_output; } TensorType _target{}; -- cgit v1.2.1