diff options
author | Sang-Hoon Park <sang-hoon.park@arm.com> | 2019-09-18 13:39:00 +0100 |
---|---|---|
committer | Georgios Pinitas <georgios.pinitas@arm.com> | 2019-10-01 12:02:45 +0000 |
commit | 2aa7fd011a4baff52dceb00a71b3674f819df8fc (patch) | |
tree | 081a8b0a75ff130d2c6179acf1fe1f1b58943412 /tests/validation | |
parent | 5c4a8e96460eb83a6caef1c69ea5cbb4893858d7 (diff) | |
download | ComputeLibrary-2aa7fd011a4baff52dceb00a71b3674f819df8fc.tar.gz |
COMPMID-2601 [CL] add mixed precision support to PoolingLayer
* PoolingLayerInfo is updated with a new flag.
* CL Kernel is updated to use FP32 accumulation.
* CL pooling layer testscases are added for mixed precision.
* Reference pooling layer is updated to use FP32 accumulation.
Change-Id: I4ab2167cc7f86c86293cf50a0ca5119c04dc9c7e
Signed-off-by: Sang-Hoon Park <sang-hoon.park@arm.com>
Reviewed-on: https://review.mlplatform.org/c/1973
Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
Tested-by: Arm Jenkins <bsgcomp@arm.com>
Reviewed-by: VidhyaSudhan Loganathan <vidhyasudhan.loganathan@arm.com>
Diffstat (limited to 'tests/validation')
-rw-r--r-- | tests/validation/CL/PoolingLayer.cpp | 19 | ||||
-rw-r--r-- | tests/validation/fixtures/PoolingLayerFixture.h | 12 | ||||
-rw-r--r-- | tests/validation/reference/PoolingLayer.cpp | 60 | ||||
-rw-r--r-- | tests/validation/reference/PoolingLayer.h | 2 |
4 files changed, 67 insertions, 26 deletions
diff --git a/tests/validation/CL/PoolingLayer.cpp b/tests/validation/CL/PoolingLayer.cpp index 7d79f3f86c..ff7c24f024 100644 --- a/tests/validation/CL/PoolingLayer.cpp +++ b/tests/validation/CL/PoolingLayer.cpp @@ -76,6 +76,8 @@ constexpr AbsoluteTolerance<float> tolerance_f16(0.01f); /**< Tolerance value constexpr AbsoluteTolerance<uint8_t> tolerance_qasymm8(1); /**< Tolerance value for comparing reference's output against implementation's output for 8-bit asymmetric type */ const auto pool_data_layout_dataset = framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC }); +const auto pool_fp_mixed_precision_dataset = framework::dataset::make("FpMixedPrecision", { true, false }); + } // namespace TEST_SUITE(CL) @@ -125,6 +127,9 @@ using CLPoolingLayerFixture = PoolingLayerValidationFixture<CLTensor, CLAccessor template <typename T> using CLSpecialPoolingLayerFixture = SpecialPoolingLayerValidationFixture<CLTensor, CLAccessor, CLPoolingLayer, T>; +template <typename T> +using CLMixedPrecesionPoolingLayerFixture = PoolingLayerValidationMixedPrecisionFixture<CLTensor, CLAccessor, CLPoolingLayer, T>; + TEST_SUITE(Float) TEST_SUITE(FP32) FIXTURE_DATA_TEST_CASE(RunSpecial, CLSpecialPoolingLayerFixture<float>, framework::DatasetMode::ALL, datasets::PoolingLayerDatasetSpecial() * framework::dataset::make("DataType", DataType::F32)) @@ -151,16 +156,18 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLPoolingLayerFixture<float>, framework::Datase TEST_SUITE_END() // FP32 TEST_SUITE(FP16) -FIXTURE_DATA_TEST_CASE(RunSmall, CLPoolingLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), combine(PoolingLayerDatasetFPSmall, - framework::dataset::make("DataType", DataType::F16))), - pool_data_layout_dataset)) +FIXTURE_DATA_TEST_CASE(RunSmall, CLMixedPrecesionPoolingLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), combine(PoolingLayerDatasetFPSmall, + framework::dataset::make("DataType", DataType::F16))), + pool_data_layout_dataset), + pool_fp_mixed_precision_dataset)) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); } -FIXTURE_DATA_TEST_CASE(RunLarge, CLPoolingLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), combine(PoolingLayerDatasetFP, - framework::dataset::make("DataType", DataType::F16))), - pool_data_layout_dataset)) +FIXTURE_DATA_TEST_CASE(RunLarge, CLMixedPrecesionPoolingLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), combine(PoolingLayerDatasetFP, + framework::dataset::make("DataType", DataType::F16))), + pool_data_layout_dataset), + pool_fp_mixed_precision_dataset)) { // Validate output validate(CLAccessor(_target), _reference, tolerance_f16); diff --git a/tests/validation/fixtures/PoolingLayerFixture.h b/tests/validation/fixtures/PoolingLayerFixture.h index 1813ef4c84..cdc2cae584 100644 --- a/tests/validation/fixtures/PoolingLayerFixture.h +++ b/tests/validation/fixtures/PoolingLayerFixture.h @@ -141,6 +141,18 @@ public: }; template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class PoolingLayerValidationMixedPrecisionFixture : public PoolingLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape shape, PoolingType pool_type, Size2D pool_size, PadStrideInfo pad_stride_info, bool exclude_padding, DataType data_type, DataLayout data_layout, bool fp_mixed_precision = false) + { + PoolingLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, PoolingLayerInfo(pool_type, pool_size, pad_stride_info, exclude_padding, fp_mixed_precision), + data_type, data_layout); + } +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> class PoolingLayerValidationQuantizedFixture : public PoolingLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T> { public: diff --git a/tests/validation/reference/PoolingLayer.cpp b/tests/validation/reference/PoolingLayer.cpp index 34b19ffb4f..010412c92b 100644 --- a/tests/validation/reference/PoolingLayer.cpp +++ b/tests/validation/reference/PoolingLayer.cpp @@ -37,8 +37,8 @@ namespace reference { using namespace arm_compute::misc::shape_calculator; -template <typename T> -SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo) +template <typename T, typename ACC_T, typename std::enable_if<is_floating_point<T>::value, int>::type> +SimpleTensor<T> pooling_layer_internal(const SimpleTensor<T> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo) { ARM_COMPUTE_UNUSED(output_qinfo); // requantization occurs in pooling_layer<uint8_t> ARM_COMPUTE_ERROR_ON(info.is_global_pooling() && (src.shape().x() != src.shape().y())); @@ -79,12 +79,12 @@ SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo wstart = std::max(wstart, 0); hstart = std::max(hstart, 0); - T max_val = std::numeric_limits<T>::lowest(); + auto max_val = std::numeric_limits<ACC_T>::lowest(); for(int y = hstart; y < hend; ++y) { for(int x = wstart; x < wend; ++x) { - const T val = src[r * h_src * w_src + y * w_src + x]; + const auto val = static_cast<ACC_T>(src[r * h_src * w_src + y * w_src + x]); if(val > max_val) { max_val = val; @@ -92,7 +92,7 @@ SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo } } - dst[r * h_dst * w_dst + h * w_dst + w] = max_val; + dst[r * h_dst * w_dst + h * w_dst + w] = static_cast<T>(max_val); } } } @@ -105,16 +105,16 @@ SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo { for(int w = 0; w < w_dst; ++w) { - T avg_val(0); - int wstart = w * pool_stride_x - pad_left; - int hstart = h * pool_stride_y - pad_top; - int wend = std::min(wstart + pool_size_x, w_src + pad_right); - int hend = std::min(hstart + pool_size_y, h_src + pad_bottom); - int pool = (hend - hstart) * (wend - wstart); - wstart = std::max(wstart, 0); - hstart = std::max(hstart, 0); - wend = std::min(wend, w_src); - hend = std::min(hend, h_src); + ACC_T avg_val(0); + int wstart = w * pool_stride_x - pad_left; + int hstart = h * pool_stride_y - pad_top; + int wend = std::min(wstart + pool_size_x, w_src + pad_right); + int hend = std::min(hstart + pool_size_y, h_src + pad_bottom); + int pool = (hend - hstart) * (wend - wstart); + wstart = std::max(wstart, 0); + hstart = std::max(hstart, 0); + wend = std::min(wend, w_src); + hend = std::min(hend, h_src); // Exclude padding pixels from the average if(exclude_padding) { @@ -127,7 +127,7 @@ SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo { for(int x = wstart; x < wend; ++x) { - avg_val += src[r * h_src * w_src + y * w_src + x]; + avg_val += static_cast<ACC_T>(src[r * h_src * w_src + y * w_src + x]); } } dst[r * h_dst * w_dst + h * w_dst + w] = avg_val / pool; @@ -138,11 +138,11 @@ SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo { for(int x = wstart; x < wend; ++x) { - const T val = src[r * h_src * w_src + y * w_src + x]; + const auto val = static_cast<ACC_T>(src[r * h_src * w_src + y * w_src + x]); avg_val += val * val; } } - dst[r * h_dst * w_dst + h * w_dst + w] = std::sqrt(avg_val / pool); + dst[r * h_dst * w_dst + h * w_dst + w] = static_cast<T>(std::sqrt(avg_val / pool)); } } } @@ -152,17 +152,37 @@ SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo return dst; } +template SimpleTensor<float> pooling_layer_internal<float>(const SimpleTensor<float> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo); +template SimpleTensor<half> pooling_layer_internal<half>(const SimpleTensor<half> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo); +template SimpleTensor<half> pooling_layer_internal<half, float>(const SimpleTensor<half> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo); + +template <typename T> +SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo) +{ + return pooling_layer_internal<T, T>(src, info, output_qinfo); +} + template <> SimpleTensor<uint8_t> pooling_layer<uint8_t>(const SimpleTensor<uint8_t> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo) { SimpleTensor<float> src_tmp = convert_from_asymmetric(src); - SimpleTensor<float> dst_tmp = pooling_layer<float>(src_tmp, info, output_qinfo); + SimpleTensor<float> dst_tmp = pooling_layer_internal<float>(src_tmp, info, output_qinfo); SimpleTensor<uint8_t> dst = convert_to_asymmetric<uint8_t>(dst_tmp, output_qinfo); return dst; } +template <> +SimpleTensor<half> pooling_layer(const SimpleTensor<half> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo) +{ + if(src.data_type() == DataType::F16 && info.fp_mixed_precision()) + { + return pooling_layer_internal<half, float>(src, info, output_qinfo); + } + + return pooling_layer_internal<half>(src, info, output_qinfo); +} + template SimpleTensor<float> pooling_layer(const SimpleTensor<float> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo); -template SimpleTensor<half> pooling_layer(const SimpleTensor<half> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo); } // namespace reference } // namespace validation } // namespace test diff --git a/tests/validation/reference/PoolingLayer.h b/tests/validation/reference/PoolingLayer.h index 1c0b7ff40d..fc36d51c02 100644 --- a/tests/validation/reference/PoolingLayer.h +++ b/tests/validation/reference/PoolingLayer.h @@ -35,6 +35,8 @@ namespace validation { namespace reference { +template <typename T, typename ACC_T = T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +SimpleTensor<T> pooling_layer_internal(const SimpleTensor<T> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo); template <typename T> SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo &info, const QuantizationInfo &output_qinfo); } // namespace reference |