diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/dataset/ShapeDatasets.h | 22 | ||||
-rw-r--r-- | tests/validation/Datasets.h | 12 | ||||
-rw-r--r-- | tests/validation/NEON/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/validation/NEON/MeanStdDev.cpp | 145 | ||||
-rw-r--r-- | tests/validation/Reference.cpp | 17 | ||||
-rw-r--r-- | tests/validation/Reference.h | 7 | ||||
-rw-r--r-- | tests/validation/ReferenceCPP.cpp | 10 | ||||
-rw-r--r-- | tests/validation/ReferenceCPP.h | 7 | ||||
-rw-r--r-- | tests/validation/TensorOperations.h | 23 |
9 files changed, 244 insertions, 0 deletions
diff --git a/tests/dataset/ShapeDatasets.h b/tests/dataset/ShapeDatasets.h index 73bdb8ea0e..d2b82cae40 100644 --- a/tests/dataset/ShapeDatasets.h +++ b/tests/dataset/ShapeDatasets.h @@ -102,6 +102,17 @@ public: } }; +/** Data set containing two small 2D tensor shapes. */ +class Small2DShapes final : public ShapeDataset<2> +{ +public: + Small2DShapes() + : ShapeDataset(TensorShape(5U, 5U), + TensorShape(640U, 480U)) + { + } +}; + /** Data set containing small tensor shapes. */ class SmallShapes final : public ShapeDataset<3> { @@ -125,6 +136,17 @@ public: { } }; + +/** Data set containing two 2D large tensor shapes. */ +class Large2DShapes final : public ShapeDataset<2> +{ +public: + Large2DShapes() + : ShapeDataset(TensorShape(1920U, 1080U), + TensorShape(4160U, 3120U)) + { + } +}; } // namespace test } // namespace arm_compute #endif diff --git a/tests/validation/Datasets.h b/tests/validation/Datasets.h index ae76fb6be3..ab21787f45 100644 --- a/tests/validation/Datasets.h +++ b/tests/validation/Datasets.h @@ -78,12 +78,24 @@ struct is_dataset<arm_compute::test::Small1DShape> : boost::mpl::true_ /// Register the data set with Boost template <> +struct is_dataset<arm_compute::test::Small2DShapes> : boost::mpl::true_ +{ +}; + +/// Register the data set with Boost +template <> struct is_dataset<arm_compute::test::LargeShapes> : boost::mpl::true_ { }; /// Register the data set with Boost template <> +struct is_dataset<arm_compute::test::Large2DShapes> : boost::mpl::true_ +{ +}; + +/// Register the data set with Boost +template <> struct is_dataset<arm_compute::test::AllDataTypes> : boost::mpl::true_ { }; diff --git a/tests/validation/NEON/CMakeLists.txt b/tests/validation/NEON/CMakeLists.txt index 52678f345b..a197f8cf0e 100644 --- a/tests/validation/NEON/CMakeLists.txt +++ b/tests/validation/NEON/CMakeLists.txt @@ -42,6 +42,7 @@ set(arm_compute_test_validation_NEON_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/NormalizationLayer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PixelWiseMultiplication.cpp ${CMAKE_CURRENT_SOURCE_DIR}/IntegralImage.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/MeanStdDev.cpp ) add_library(arm_compute_test_validation_NEON OBJECT diff --git a/tests/validation/NEON/MeanStdDev.cpp b/tests/validation/NEON/MeanStdDev.cpp new file mode 100644 index 0000000000..79a30f62b2 --- /dev/null +++ b/tests/validation/NEON/MeanStdDev.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "Globals.h" +#include "NEON/Helper.h" +#include "NEON/NEAccessor.h" +#include "TensorLibrary.h" +#include "TypePrinter.h" +#include "Utils.h" +#include "validation/Datasets.h" +#include "validation/Reference.h" +#include "validation/Validation.h" + +#include "arm_compute/core/Helpers.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEMeanStdDev.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" + +#include "boost_wrapper.h" + +#include <random> +#include <string> + +using namespace arm_compute; +using namespace arm_compute::test; +using namespace arm_compute::test::neon; +using namespace arm_compute::test::validation; + +namespace +{ +/** Compute Neon mean and standard deviation function. + * + * @param[in] shape Shape of the input tensors. + * + * @return Computed mean and standard deviation. + */ +std::pair<float, float> compute_mean_and_standard_deviation(const TensorShape &shape) +{ + // Create tensor + Tensor src = create_tensor(shape, DataType::U8); + + // Create output variables + float mean = 0.f; + float std_dev = 0.f; + + // Create mean and standard deviation configure function + NEMeanStdDev mean_std_dev_image; + mean_std_dev_image.configure(&src, &mean, &std_dev); + + // Allocate tensors + src.allocator()->allocate(); + + BOOST_TEST(!src.info()->is_resizable()); + + // Fill tensor + library->fill_tensor_uniform(NEAccessor(src), 0); + + // Compute function + mean_std_dev_image.run(); + + return std::make_pair(mean, std_dev); +} +} // namespace + +#ifndef DOXYGEN_SKIP_THIS +BOOST_AUTO_TEST_SUITE(NEON) +BOOST_AUTO_TEST_SUITE(MeanStdDev) + +BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) +BOOST_DATA_TEST_CASE(Configuration, Small2DShapes() + Large2DShapes(), shape) +{ + // Create tensor + Tensor src = create_tensor(shape, DataType::U8); + + // Create output variables + float mean = 0.f; + float std_dev = 0.f; + + BOOST_TEST(src.info()->is_resizable()); + + // Create mean and standard deviation configure function + NEMeanStdDev mean_std_dev_image; + mean_std_dev_image.configure(&src, &mean, &std_dev); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding(0, required_padding(shape.x(), 16), 0, 0); + validate(src.info()->padding(), padding); +} + +BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) +BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes(), shape) +{ + // Compute function + std::pair<float, float> output = compute_mean_and_standard_deviation(shape); + + // Compute reference + std::pair<float, float> ref_output = Reference::compute_reference_mean_and_standard_deviation(shape); + + // Validate output + BOOST_TEST(static_cast<int>(output.first) == static_cast<int>(ref_output.first)); + BOOST_TEST(static_cast<int>(output.second) == static_cast<int>(ref_output.second)); +} + +BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) +BOOST_DATA_TEST_CASE(RunLarge, Large2DShapes(), shape) +{ + // Compute function + std::pair<float, float> output = compute_mean_and_standard_deviation(shape); + + // Compute reference + std::pair<float, float> ref_output = Reference::compute_reference_mean_and_standard_deviation(shape); + + // Validate output + BOOST_TEST(static_cast<int>(output.first) == static_cast<int>(ref_output.first)); + BOOST_TEST(static_cast<int>(output.second) == static_cast<int>(ref_output.second)); +} + +BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() +#endif diff --git a/tests/validation/Reference.cpp b/tests/validation/Reference.cpp index 263c57b16b..5f49caead0 100644 --- a/tests/validation/Reference.cpp +++ b/tests/validation/Reference.cpp @@ -39,6 +39,23 @@ namespace test { namespace validation { +std::pair<float, float> Reference::compute_reference_mean_and_standard_deviation(const TensorShape &shape) +{ + // Create reference + RawTensor ref_src = library->get(shape, DataType::U8); + + // Create output variables + float mean; + float std_dev; + + // Fill reference + library->fill_tensor_uniform(ref_src, 0); + + // Compute reference + ReferenceCPP::mean_and_standard_deviation(ref_src, mean, std_dev); + + return std::make_pair(mean, std_dev); +} RawTensor Reference::compute_reference_integral_image(const TensorShape &shape) { // Create reference diff --git a/tests/validation/Reference.h b/tests/validation/Reference.h index 4e5b462f9e..06a38c41f2 100644 --- a/tests/validation/Reference.h +++ b/tests/validation/Reference.h @@ -37,6 +37,13 @@ namespace validation class Reference { public: + /** Compute reference mean and standard deviation. + * + * @param[in] shape Shape of the input tensors. + * + * @return Computed mean and standard deviation. + */ + static std::pair<float, float> compute_reference_mean_and_standard_deviation(const TensorShape &shape); /** Compute reference integral image. * * @param[in] shape Shape of the input and output tensors. diff --git a/tests/validation/ReferenceCPP.cpp b/tests/validation/ReferenceCPP.cpp index ddb84835c3..5c429ea864 100644 --- a/tests/validation/ReferenceCPP.cpp +++ b/tests/validation/ReferenceCPP.cpp @@ -56,6 +56,15 @@ void ReferenceCPP::absolute_difference(const RawTensor &src1, const RawTensor &s TensorVariant d = TensorFactory::get_tensor(dst); boost::apply_visitor(absolute_difference_visitor(), s1, s2, d); } + +// Mean and standard deviation +void ReferenceCPP::mean_and_standard_deviation(const RawTensor &src, float &mean, float &std_dev) +{ + ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8); + const Tensor<uint8_t> s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast<const uint8_t *>(src.data())); + tensor_operations::mean_and_standard_deviation(s, mean, std_dev); +} + // Integral image void ReferenceCPP::integral_image(const RawTensor &src, RawTensor &dst) { @@ -64,6 +73,7 @@ void ReferenceCPP::integral_image(const RawTensor &src, RawTensor &dst) Tensor<uint32_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<uint32_t *>(dst.data())); tensor_operations::integral_image(s, d); } + // Accumulate void ReferenceCPP::accumulate(const RawTensor &src, RawTensor &dst) { diff --git a/tests/validation/ReferenceCPP.h b/tests/validation/ReferenceCPP.h index be5a733896..4173b8bc1d 100644 --- a/tests/validation/ReferenceCPP.h +++ b/tests/validation/ReferenceCPP.h @@ -42,6 +42,13 @@ namespace validation class ReferenceCPP final : public Reference { public: + /** Function to compute the mean and standard deviation of a tensor. + * + * @param[in] src Input tensor. + * @param[out] mean Mean of the tensor. + * @param[out] std_dev Standard deviation of the tensor + */ + static void mean_and_standard_deviation(const RawTensor &src, float &mean, float &std_dev); /** Function to compute the integral image of a tensor. * * @param[in] src Input tensor. diff --git a/tests/validation/TensorOperations.h b/tests/validation/TensorOperations.h index 5e27e9d3a0..119be02423 100644 --- a/tests/validation/TensorOperations.h +++ b/tests/validation/TensorOperations.h @@ -221,6 +221,29 @@ void apply_2d_spatial_filter(Coordinates coord, const Tensor<T1> &in, Tensor<T3> } } // namespace +// Mean Standard Deviation +template <typename T1> +void mean_and_standard_deviation(const Tensor<T1> &in, float &mean, float &std_dev) +{ + int num_elements = in.num_elements(); + + // Calculate mean + mean = 0.f; + for(int i = 0; i < num_elements; ++i) + { + mean += in[i]; + } + mean /= num_elements; + + // Calculate standard deviation + std_dev = 0.f; + for(int i = 0; i < num_elements; ++i) + { + std_dev += (mean - in[i]) * (mean - in[i]); + } + std_dev = sqrt(std_dev / num_elements); +} + // Integral Image void integral_image(const Tensor<uint8_t> &in, Tensor<uint32_t> &out) { |