diff options
Diffstat (limited to 'tests/validation')
-rw-r--r-- | tests/validation/CL/ConvolutionLayer.cpp | 117 | ||||
-rw-r--r-- | tests/validation/CL/WeightsReshape.cpp | 4 | ||||
-rw-r--r-- | tests/validation/fixtures/ConvolutionLayerFixture.h | 17 | ||||
-rw-r--r-- | tests/validation/reference/ConvolutionLayer.cpp | 49 | ||||
-rw-r--r-- | tests/validation/reference/ConvolutionLayer.h | 2 |
5 files changed, 154 insertions, 35 deletions
diff --git a/tests/validation/CL/ConvolutionLayer.cpp b/tests/validation/CL/ConvolutionLayer.cpp index 54fdc0c386..5c96cd4c59 100644 --- a/tests/validation/CL/ConvolutionLayer.cpp +++ b/tests/validation/CL/ConvolutionLayer.cpp @@ -58,6 +58,14 @@ const auto CNNDataTypes = framework::dataset::make("DataType", DataType::F32, DataType::QASYMM8, }); + +/** Grouped CNN data types */ +const auto GroupedCNNDataTypes = framework::dataset::make("DataType", +{ + DataType::F16, + DataType::F32 +}); + const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo", { ActivationLayerInfo(), @@ -219,7 +227,7 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMConvolutionLayerFixture<half>, framework: // Validate output validate(CLAccessor(_target), _reference, tolerance_f16, tolerance_num); } -TEST_SUITE_END() +TEST_SUITE_END() // FP16 TEST_SUITE(FP32) @@ -244,8 +252,8 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMConvolutionLayerFixture<float>, framework // Validate output validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, absolute_tolerance_float); } -TEST_SUITE_END() -TEST_SUITE_END() +TEST_SUITE_END() // FP32 +TEST_SUITE_END() // Float template <typename T> using CLGEMMConvolutionLayerQuantizedFixture = ConvolutionValidationQuantizedFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T>; @@ -280,11 +288,106 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMConvolutionLayerQuantizedFixture<uint8_t> // Validate output validate(CLAccessor(_target), _reference, tolerance_qasymm8); } -TEST_SUITE_END() -TEST_SUITE_END() +TEST_SUITE_END() // QASYMM8 +TEST_SUITE_END() // Quantized -TEST_SUITE_END() -TEST_SUITE_END() +TEST_SUITE_END() // GEMMConvolutionLayer + +template <typename T> +using CLGEMMGroupedConvolutionLayerFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T>; + +TEST_SUITE(GroupedGEMMConvolutionLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(framework::dataset::concat(datasets::SmallGroupedConvolutionLayerDataset(), datasets::LargeGroupedConvolutionLayerDataset()), + GroupedCNNDataTypes), + ActivationFunctionsDataset), + input_shape, weights_shape, bias_shape, output_shape, info, dilation, data_type, act_info) +{ + ARM_COMPUTE_ERROR_ON((input_shape[2] % weights_shape[2]) != 0); + + // The number of groups is calculated dividing the number of input channels of the input tensor by the number of input channels of the weights shape + const int num_groups = input_shape[2] / weights_shape[2]; + + // Create tensors + CLTensor src = create_tensor<CLTensor>(input_shape, data_type); + CLTensor weights = create_tensor<CLTensor>(weights_shape, data_type, 1); + CLTensor bias = create_tensor<CLTensor>(bias_shape, data_type, 1); + CLTensor dst = create_tensor<CLTensor>(output_shape, data_type, 1); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(weights.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLGEMMConvolutionLayer conv; + conv.configure(&src, &weights, &bias, &dst, info, WeightsInfo(), dilation, act_info, num_groups); + + // Validate valid region + const ValidRegion src_valid_region = shape_to_valid_region(input_shape); + const ValidRegion weights_valid_region = shape_to_valid_region(weights_shape); + const ValidRegion bias_valid_region = shape_to_valid_region(bias_shape); + const ValidRegion dst_valid_region = shape_to_valid_region(output_shape); + + validate(src.info()->valid_region(), src_valid_region); + validate(weights.info()->valid_region(), weights_valid_region); + validate(bias.info()->valid_region(), bias_valid_region); + validate(dst.info()->valid_region(), dst_valid_region); + + // Validate padding + //TODO(COMPMID-415) Need to validate padding? +} + +TEST_SUITE(Float) +TEST_SUITE(FP32) + +FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMGroupedConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(datasets::SmallGroupedConvolutionLayerDataset(), + framework::dataset::make("ReshapeWeights", { true })), + framework::dataset::make("DataType", DataType::F32)), + framework::dataset::make("DataLayout", { DataLayout::NCHW })), + ActivationFunctionsDataset)) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32, tolerance_num); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMGroupedConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::LargeGroupedConvolutionLayerDataset(), + framework::dataset::make("ReshapeWeights", { true })), + framework::dataset::make("DataType", DataType::F32)), + framework::dataset::make("DataLayout", { DataLayout::NCHW })), + ActivationFunctionsDataset)) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32, tolerance_num); +} +TEST_SUITE_END() // FP32 + +TEST_SUITE(FP16) + +FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMGroupedConvolutionLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(datasets::SmallGroupedConvolutionLayerDataset(), + framework::dataset::make("ReshapeWeights", { true })), + framework::dataset::make("DataType", DataType::F16)), + framework::dataset::make("DataLayout", { DataLayout::NCHW })), + ActivationFunctionsDataset)) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32, tolerance_num); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMGroupedConvolutionLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::LargeGroupedConvolutionLayerDataset(), + framework::dataset::make("ReshapeWeights", { true })), + framework::dataset::make("DataType", DataType::F16)), + framework::dataset::make("DataLayout", { DataLayout::NCHW })), + ActivationFunctionsDataset)) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32, tolerance_num); +} +TEST_SUITE_END() // FP16 +TEST_SUITE_END() // Float + +TEST_SUITE_END() // GroupedGEMMConvolutionLayer +TEST_SUITE_END() // CL } // namespace validation } // namespace test } // namespace arm_compute diff --git a/tests/validation/CL/WeightsReshape.cpp b/tests/validation/CL/WeightsReshape.cpp index 6dae0c7625..30c231d499 100644 --- a/tests/validation/CL/WeightsReshape.cpp +++ b/tests/validation/CL/WeightsReshape.cpp @@ -79,7 +79,7 @@ TEST_SUITE(FP32) FIXTURE_DATA_TEST_CASE(RunSmall, CLWeightsReshapeFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(datasets::GroupedWeightsSmallShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("HasBias", { true, false })), - framework::dataset::make("NumGroups", { 1, 2, 3 }))) + framework::dataset::make("NumGroups", { 1, 2, 3, 4 }))) { // Validate output validate(CLAccessor(_target), _reference); @@ -87,7 +87,7 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLWeightsReshapeFixture<float>, framework::Data FIXTURE_DATA_TEST_CASE(RunLarge, CLWeightsReshapeFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::GroupedWeightsLargeShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("HasBias", { true, false })), - framework::dataset::make("NumGroups", { 1, 2, 3 }))) + framework::dataset::make("NumGroups", { 1, 2, 3, 4 }))) { // Validate output validate(CLAccessor(_target), _reference); diff --git a/tests/validation/fixtures/ConvolutionLayerFixture.h b/tests/validation/fixtures/ConvolutionLayerFixture.h index 4a6326480c..3b420eac09 100644 --- a/tests/validation/fixtures/ConvolutionLayerFixture.h +++ b/tests/validation/fixtures/ConvolutionLayerFixture.h @@ -102,6 +102,10 @@ protected: TensorType compute_target(TensorShape input_shape, TensorShape weights_shape, const TensorShape &bias_shape, TensorShape output_shape, const PadStrideInfo &info, bool reshape_weights, const Size2D &dilation, const ActivationLayerInfo act_info) { + ARM_COMPUTE_ERROR_ON((input_shape[2] % weights_shape[2]) != 0); + + const unsigned int num_groups = input_shape[2] / weights_shape[2]; + if(_data_layout == DataLayout::NHWC) { permute(input_shape, PermutationVector(2U, 0U, 1U)); @@ -123,7 +127,7 @@ protected: // Create and configure function FunctionType conv; - conv.configure(&src, &weights, &bias, &dst, info, weights_info, dilation, act_info); + conv.configure(&src, &weights, &bias, &dst, info, weights_info, dilation, act_info, num_groups); ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); ARM_COMPUTE_EXPECT(weights.info()->is_resizable(), framework::LogLevel::ERRORS); @@ -155,6 +159,10 @@ protected: SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info, const Size2D &dilation, const ActivationLayerInfo act_info) { + ARM_COMPUTE_ERROR_ON((input_shape[2] % weights_shape[2]) != 0); + + const unsigned int num_groups = input_shape[2] / weights_shape[2]; + // Create reference SimpleTensor<T> src{ input_shape, _data_type, 1, _quantization_info }; SimpleTensor<T> weights{ weights_shape, _data_type, 1, _quantization_info }; @@ -165,9 +173,9 @@ protected: fill(weights, 1); fill(bias, 2); - return (act_info.enabled()) ? reference::activation_layer<T>(reference::convolution_layer<T>(src, weights, bias, output_shape, info, dilation), + return (act_info.enabled()) ? reference::activation_layer<T>(reference::convolution_layer<T>(src, weights, bias, output_shape, info, dilation, num_groups), act_info) : - reference::convolution_layer<T>(src, weights, bias, output_shape, info, dilation); + reference::convolution_layer<T>(src, weights, bias, output_shape, info, dilation, num_groups); } TensorType _target{}; @@ -187,7 +195,8 @@ public: void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, Size2D dilation, bool reshape_weights, DataType data_type, DataLayout data_layout, ActivationLayerInfo act_info) { - ConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, dilation, reshape_weights, data_type, data_layout, + ConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, dilation, reshape_weights, + data_type, data_layout, QuantizationInfo(), act_info); } }; diff --git a/tests/validation/reference/ConvolutionLayer.cpp b/tests/validation/reference/ConvolutionLayer.cpp index 2d314059dd..f41a6fc8c4 100644 --- a/tests/validation/reference/ConvolutionLayer.cpp +++ b/tests/validation/reference/ConvolutionLayer.cpp @@ -47,8 +47,10 @@ namespace template <typename T, typename TB> SimpleTensor<T> convolution_layer_nchw(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, SimpleTensor<T> &dst, const PadStrideInfo &info, - const Size2D &dilation) + const Size2D &dilation, unsigned int num_groups) { + ARM_COMPUTE_ERROR_ON((src.shape()[2] / num_groups) != weights.shape()[2]); + // Compute reference const int width_in = src.shape().x(); const int height_in = src.shape().y(); @@ -78,23 +80,28 @@ SimpleTensor<T> convolution_layer_nchw(const SimpleTensor<T> &src, const SimpleT { for(int xi = start_xi; xi < start_xi + end_xi; xi += stride_xi) { - for(int ofm = 0; ofm < depth_out; ++ofm) + for(int group = 0; group < static_cast<int>(num_groups); ++group) { - // Compute input and output offsets - const int offset_in = r * width_in * height_in * depth_in; - const int xo = (xi - start_xi) / stride_xi; - const int yo = (yi - start_yi) / stride_yi; - const int offset_out = xo + yo * width_out + ofm * width_out * height_out + r * width_out * height_out * depth_out; + for(int ofm = 0; ofm < static_cast<int>(depth_out / num_groups); ++ofm) + { + // Compute input and output offsets + const int offset_in = r * width_in * height_in * depth_in + (group * (depth_in / num_groups) * width_in * height_in); + const int xo = (xi - start_xi) / stride_xi; + const int yo = (yi - start_yi) / stride_yi; + const int offset_out = xo + yo * width_out + ((ofm + group * (depth_out / num_groups)) * width_out * height_out) + (r * width_out * height_out * depth_out); + const int offset_w = (ofm + group * (depth_out / num_groups)) * width_weights * height_weights * depth_weights; + const int offset_b = (ofm + group * (depth_out / num_groups)); - ARM_COMPUTE_ASSERT(xo < width_out); - ARM_COMPUTE_ASSERT(yo < height_out); + ARM_COMPUTE_ASSERT(xo < width_out); + ARM_COMPUTE_ASSERT(yo < height_out); - // Compute 3D convolution - convolution_3d::detail::convolution3d(src, weights, bias, dst, - offset_in, ofm * width_weights * height_weights * depth_weights, ofm, offset_out, - xi, yi, - width_in, height_in, depth_in, - width_weights, height_weights, dilation.x(), dilation.y()); + // Compute 3D convolution + convolution_3d::detail::convolution3d(src, weights, bias, dst, + offset_in, offset_w, offset_b, offset_out, + xi, yi, + width_in, height_in, (depth_in / num_groups), + width_weights, height_weights, dilation.x(), dilation.y()); + } } } } @@ -104,7 +111,7 @@ SimpleTensor<T> convolution_layer_nchw(const SimpleTensor<T> &src, const SimpleT } template <typename T, typename TB> SimpleTensor<T> convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, const TensorShape &output_shape, const PadStrideInfo &info, - const Size2D &dilation) + const Size2D &dilation, unsigned int num_groups) { // Create reference SimpleTensor<T> dst{ output_shape, src.data_type(), 1, src.quantization_info() }; @@ -115,20 +122,20 @@ SimpleTensor<T> convolution_layer(const SimpleTensor<T> &src, const SimpleTensor SimpleTensor<T> weights_nchw = reference::permute<T>(weights, PermutationVector(1U, 2U, 0U)); SimpleTensor<T> dst_nchw = reference::permute<T>(dst, PermutationVector(1U, 2U, 0U)); - return reference::permute<T>(convolution_layer_nchw(src_nchw, weights_nchw, bias, dst_nchw, info, dilation), PermutationVector(2U, 0U, 1U)); + return reference::permute<T>(convolution_layer_nchw(src_nchw, weights_nchw, bias, dst_nchw, info, dilation, num_groups), PermutationVector(2U, 0U, 1U)); } else { - return convolution_layer_nchw(src, weights, bias, dst, info, dilation); + return convolution_layer_nchw(src, weights, bias, dst, info, dilation, num_groups); } } template SimpleTensor<float> convolution_layer(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &bias, const TensorShape &output_shape, - const PadStrideInfo &info, const Size2D &dilation); + const PadStrideInfo &info, const Size2D &dilation, unsigned int num_groups); template SimpleTensor<half> convolution_layer(const SimpleTensor<half> &src, const SimpleTensor<half> &weights, const SimpleTensor<half> &bias, const TensorShape &output_shape, - const PadStrideInfo &info, const Size2D &dilation); + const PadStrideInfo &info, const Size2D &dilation, unsigned int num_groups); template SimpleTensor<uint8_t> convolution_layer(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &bias, const TensorShape &output_shape, - const PadStrideInfo &info, const Size2D &dilation); + const PadStrideInfo &info, const Size2D &dilation, unsigned int num_groups); } // namespace reference } // namespace validation } // namespace test diff --git a/tests/validation/reference/ConvolutionLayer.h b/tests/validation/reference/ConvolutionLayer.h index ff3b1531f4..ccce53a209 100644 --- a/tests/validation/reference/ConvolutionLayer.h +++ b/tests/validation/reference/ConvolutionLayer.h @@ -37,7 +37,7 @@ namespace reference { template <typename T, typename TB> SimpleTensor<T> convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, const TensorShape &output_shape, const PadStrideInfo &info, - const Size2D &dilation = Size2D(1U, 1U)); + const Size2D &dilation = Size2D(1U, 1U), unsigned int num_groups = 1); } // namespace reference } // namespace validation } // namespace test |