diff options
Diffstat (limited to 'tests/validation')
185 files changed, 11594 insertions, 15792 deletions
diff --git a/tests/validation/CL/ActivationLayer.cpp b/tests/validation/CL/ActivationLayer.cpp new file mode 100644 index 0000000000..097fb638f9 --- /dev/null +++ b/tests/validation/CL/ActivationLayer.cpp @@ -0,0 +1,247 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLActivationLayer.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ActivationFunctionsDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ActivationLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Define tolerance of the activation layer. + * + * @param[in] activation The activation function used. + * @param[in] data_type Data type. + * + * @return Tolerance depending on the activation function. + */ +AbsoluteTolerance<float> tolerance(ActivationLayerInfo::ActivationFunction activation, DataType data_type) +{ + constexpr float epsilon = 1e-6f; + + switch(activation) + { + case ActivationLayerInfo::ActivationFunction::LINEAR: + return AbsoluteTolerance<float>(data_type == DataType::F16 ? 0.2f : epsilon); + case ActivationLayerInfo::ActivationFunction::SQUARE: + return AbsoluteTolerance<float>(data_type == DataType::F16 ? 0.1f : epsilon); + case ActivationLayerInfo::ActivationFunction::LOGISTIC: + if(is_data_type_fixed_point(data_type)) + { + return AbsoluteTolerance<float>(5.f); + } + else + { + return AbsoluteTolerance<float>(data_type == DataType::F16 ? 0.001f : epsilon); + } + case ActivationLayerInfo::ActivationFunction::LEAKY_RELU: + return AbsoluteTolerance<float>(data_type == DataType::F16 ? 0.00001f : epsilon); + case ActivationLayerInfo::ActivationFunction::SOFT_RELU: + case ActivationLayerInfo::ActivationFunction::SQRT: + if(is_data_type_fixed_point(data_type)) + { + return AbsoluteTolerance<float>(5.f); + } + else + { + return AbsoluteTolerance<float>(data_type == DataType::F16 ? 0.01f : 0.00001f); + } + case ActivationLayerInfo::ActivationFunction::TANH: + if(is_data_type_fixed_point(data_type)) + { + return AbsoluteTolerance<float>(5.f); + } + else + { + return AbsoluteTolerance<float>(data_type == DataType::F16 ? 0.001f : 0.00001f); + } + default: + return AbsoluteTolerance<float>(epsilon); + } +} + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ + DataType::F16, + DataType::F32, + DataType::QS8, + DataType::QS16, +}); + +/** Input data sets. */ +const auto ActivationDataset = combine(combine(framework::dataset::make("InPlace", { false, true }), datasets::ActivationFunctions()), framework::dataset::make("AlphaBeta", { 0.5f, 1.f })); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(ActivationLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), CNNDataTypes), framework::dataset::make("InPlace", { false, true })), + shape, data_type, in_place) +{ + // Set fixed point position data type allowed + const int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + // Create tensors + CLTensor src = create_tensor<CLTensor>(shape, data_type, 1, fixed_point_position); + CLTensor dst = create_tensor<CLTensor>(shape, data_type, 1, fixed_point_position); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLActivationLayer act_layer; + + if(in_place) + { + act_layer.configure(&src, nullptr, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::ABS)); + } + else + { + act_layer.configure(&src, &dst, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::ABS)); + } + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + + if(!in_place) + { + validate(dst.info()->valid_region(), valid_region); + } + + // Validate padding + const int step = 16 / arm_compute::data_size_from_type(data_type); + const PaddingSize padding = PaddingCalculator(shape.x(), step).required_padding(); + validate(src.info()->padding(), padding); + + if(!in_place) + { + validate(dst.info()->padding(), padding); + } +} + +template <typename T> +using CLActivationLayerFixture = ActivationValidationFixture<CLTensor, CLAccessor, CLActivationLayer, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLActivationLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance(_function, _data_type)); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLActivationLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance(_function, _data_type)); +} +TEST_SUITE_END() + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLActivationLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), ActivationDataset), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance(_function, _data_type)); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLActivationLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), ActivationDataset), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance(_function, _data_type)); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using CLActivationLayerFixedPointFixture = ActivationValidationFixedPointFixture<CLTensor, CLAccessor, CLActivationLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// We test for fixed point precision [3,5] because [1,2] and [6,7] ranges cause +// overflowing issues in most of the transcendentals functions. +FIXTURE_DATA_TEST_CASE(RunSmall, CLActivationLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 3, 6))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance(_function, _data_type)); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLActivationLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 3, 6))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance(_function, _data_type)); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14 +FIXTURE_DATA_TEST_CASE(RunSmall, CLActivationLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance(_function, _data_type)); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLActivationLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance(_function, _data_type)); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/ArithmeticAddition.cpp b/tests/validation/CL/ArithmeticAddition.cpp deleted file mode 100644 index fc1bf5905d..0000000000 --- a/tests/validation/CL/ArithmeticAddition.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "tests/Globals.h" -#include "tests/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/CL/functions/CLArithmeticAddition.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::validation; - -namespace -{ -/** Compute Neon arithmetic addition function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Overflow policy of the operation. - * @param[in] fixed_point_position (Optional) Fixed point position that expresses the number of bits for the fractional part of the number when the tensor's data type is QS8 or QS16 (default = 0). - * - * @return Computed output tensor. - */ -CLTensor compute_arithmetic_addition(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy policy, int fixed_point_position = 0) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, dt_in0, 1, fixed_point_position); - CLTensor src2 = create_tensor<CLTensor>(shape, dt_in1, 1, fixed_point_position); - CLTensor dst = create_tensor<CLTensor>(shape, dt_out, 1, fixed_point_position); - - // Create and configure function - CLArithmeticAddition add; - add.configure(&src1, &src2, &dst, policy); - - // Allocate tensors - src1.allocator()->allocate(); - src2.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src1.info()->is_resizable()); - BOOST_TEST(!src2.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src1), 0); - library->fill_tensor_uniform(CLAccessor(src2), 1); - - // Compute function - add.run(); - - return dst; -} - -void validate_configuration(const CLTensor &src1, const CLTensor &src2, CLTensor &dst, TensorShape shape, ConvertPolicy policy) -{ - BOOST_TEST(src1.info()->is_resizable()); - BOOST_TEST(src2.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLArithmeticAddition add; - add.configure(&src1, &src2, &dst, policy); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src1.info()->valid_region(), valid_region); - validate(src2.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src1.info()->padding(), padding); - validate(src2.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(ArithmeticAddition) - -BOOST_AUTO_TEST_SUITE(U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor src2 = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, DataType::U8, DataType::U8, DataType::U8, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::U8, DataType::U8, DataType::U8, policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, dt); - CLTensor src2 = create_tensor<CLTensor>(shape, DataType::S16); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::S16); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, dt, DataType::S16, DataType::S16, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, dt, DataType::S16, DataType::S16, policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, dt, DataType::S16, DataType::S16, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, dt, DataType::S16, DataType::S16, policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Quantized) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 7), - shape, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 7), - shape, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 15), - shape, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 15), - shape, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(F16) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, DataType::F16, DataType::F16, DataType::F16, ConvertPolicy::WRAP); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::F16, DataType::F16, DataType::F16, ConvertPolicy::WRAP); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(F32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, DataType::F32); - CLTensor src2 = create_tensor<CLTensor>(shape, DataType::F32); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::F32); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, DataType::F32, DataType::F32, DataType::F32, ConvertPolicy::WRAP); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::F32, DataType::F32, DataType::F32, ConvertPolicy::WRAP); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Compute function - CLTensor dst = compute_arithmetic_addition(shape, DataType::F32, DataType::F32, DataType::F32, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::F32, DataType::F32, DataType::F32, policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/ArithmeticSubtraction.cpp b/tests/validation/CL/ArithmeticSubtraction.cpp deleted file mode 100644 index 086281cdda..0000000000 --- a/tests/validation/CL/ArithmeticSubtraction.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "tests/Globals.h" -#include "tests/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/CL/functions/CLArithmeticSubtraction.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::validation; - -namespace -{ -/** Compute Neon arithmetic subtraction function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Overflow policy of the operation. - * @param[in] fixed_point_position (Optional) Fixed point position that expresses the number of bits for the fractional part of the number when the tensor's data type is QS8 or QS16 (default = 0). - * - * @return Computed output tensor. - */ -CLTensor compute_arithmetic_subtraction(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy policy, int fixed_point_position = 0) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, dt_in0, 1, fixed_point_position); - CLTensor src2 = create_tensor<CLTensor>(shape, dt_in1, 1, fixed_point_position); - CLTensor dst = create_tensor<CLTensor>(shape, dt_out, 1, fixed_point_position); - - // Create and configure function - CLArithmeticSubtraction sub; - sub.configure(&src1, &src2, &dst, policy); - - // Allocate tensors - src1.allocator()->allocate(); - src2.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src1.info()->is_resizable()); - BOOST_TEST(!src2.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src1), 0); - library->fill_tensor_uniform(CLAccessor(src2), 1); - - // Compute function - sub.run(); - - return dst; -} - -void validate_configuration(const CLTensor &src1, const CLTensor &src2, CLTensor &dst, TensorShape shape, ConvertPolicy policy) -{ - BOOST_TEST(src1.info()->is_resizable()); - BOOST_TEST(src2.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLArithmeticSubtraction sub; - sub.configure(&src1, &src2, &dst, policy); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src1.info()->valid_region(), valid_region); - validate(src2.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src1.info()->padding(), padding); - validate(src2.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(ArithmeticSubtraction) - -BOOST_AUTO_TEST_SUITE(U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor src2 = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, DataType::U8, DataType::U8, DataType::U8, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::U8, DataType::U8, DataType::U8, policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, dt); - CLTensor src2 = create_tensor<CLTensor>(shape, DataType::S16); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::S16); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, dt, DataType::S16, DataType::S16, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, dt, DataType::S16, DataType::S16, policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, dt, DataType::S16, DataType::S16, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, dt, DataType::S16, DataType::S16, policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Quantized) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 7), - shape, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 7), - shape, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 15), - shape, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 15), - shape, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, DataType::F32); - CLTensor src2 = create_tensor<CLTensor>(shape, DataType::F32); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::F32); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, DataType::F32, DataType::F32, DataType::F32, ConvertPolicy::WRAP); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::F32, DataType::F32, DataType::F32, ConvertPolicy::WRAP); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Compute function - CLTensor dst = compute_arithmetic_subtraction(shape, DataType::F32, DataType::F32, DataType::F32, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::F32, DataType::F32, DataType::F32, policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/BatchNormalizationLayer.cpp b/tests/validation/CL/BatchNormalizationLayer.cpp deleted file mode 100644 index abcc619cb8..0000000000 --- a/tests/validation/CL/BatchNormalizationLayer.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "dataset/BatchNormalizationLayerDataset.h" -#include "tests/validation/Helpers.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/CL/functions/CLBatchNormalizationLayer.h" -#include "arm_compute/runtime/Tensor.h" -#include "arm_compute/runtime/TensorAllocator.h" - -#include <random> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -const float tolerance_f = 1e-05; /**< Tolerance value for comparing reference's output against floating point implementation's output */ -const float tolerance_qs8 = 3; /**< Tolerance value for comparing reference's output against quantized implementation's output */ -const float tolerance_qs16 = 6; /**< Tolerance value for comparing reference's output against quantized implementation's output */ - -/** Compute Neon batch normalization function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt Data type of input and output tensors. - * @param[in] norm_info Normalization Layer information. - * - * @return Computed output tensor. - */ -CLTensor compute_reference_batch_normalization_layer(const TensorShape &shape0, const TensorShape &shape1, DataType dt, float epsilon, int fixed_point_position = 0) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape0, dt, 1, fixed_point_position); - CLTensor dst = create_tensor<CLTensor>(shape0, dt, 1, fixed_point_position); - CLTensor mean = create_tensor<CLTensor>(shape1, dt, 1, fixed_point_position); - CLTensor var = create_tensor<CLTensor>(shape1, dt, 1, fixed_point_position); - CLTensor beta = create_tensor<CLTensor>(shape1, dt, 1, fixed_point_position); - CLTensor gamma = create_tensor<CLTensor>(shape1, dt, 1, fixed_point_position); - - // Create and configure function - CLBatchNormalizationLayer norm; - norm.configure(&src, &dst, &mean, &var, &beta, &gamma, epsilon); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - mean.allocator()->allocate(); - var.allocator()->allocate(); - beta.allocator()->allocate(); - gamma.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - BOOST_TEST(!mean.info()->is_resizable()); - BOOST_TEST(!var.info()->is_resizable()); - BOOST_TEST(!beta.info()->is_resizable()); - BOOST_TEST(!gamma.info()->is_resizable()); - - // Fill tensors - if(dt == DataType::F32) - { - float min_bound = 0.f; - float max_bound = 0.f; - std::tie(min_bound, max_bound) = get_batchnormalization_layer_test_bounds<float>(); - std::uniform_real_distribution<> distribution(min_bound, max_bound); - std::uniform_real_distribution<> distribution_var(0, max_bound); - library->fill(CLAccessor(src), distribution, 0); - library->fill(CLAccessor(mean), distribution, 1); - library->fill(CLAccessor(var), distribution_var, 0); - library->fill(CLAccessor(beta), distribution, 3); - library->fill(CLAccessor(gamma), distribution, 4); - } - else - { - int min_bound = 0; - int max_bound = 0; - if(dt == DataType::QS8) - { - std::tie(min_bound, max_bound) = get_batchnormalization_layer_test_bounds<int8_t>(fixed_point_position); - } - else - { - std::tie(min_bound, max_bound) = get_batchnormalization_layer_test_bounds<int16_t>(fixed_point_position); - } - std::uniform_int_distribution<> distribution(min_bound, max_bound); - std::uniform_int_distribution<> distribution_var(0, max_bound); - library->fill(CLAccessor(src), distribution, 0); - library->fill(CLAccessor(mean), distribution, 1); - library->fill(CLAccessor(var), distribution_var, 0); - library->fill(CLAccessor(beta), distribution, 3); - library->fill(CLAccessor(gamma), distribution, 4); - } - - // Compute function - norm.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(BatchNormalizationLayer) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make({ DataType::QS8, DataType::QS16, DataType::F32 }), obj, dt) -{ - // Set fixed point position data type allowed - int fixed_point_position = (arm_compute::is_data_type_fixed_point(dt)) ? 3 : 0; - - // Create tensors - CLTensor src = create_tensor<CLTensor>(obj.shape0, dt, 1, fixed_point_position); - CLTensor dst = create_tensor<CLTensor>(obj.shape0, dt, 1, fixed_point_position); - CLTensor mean = create_tensor<CLTensor>(obj.shape1, dt, 1, fixed_point_position); - CLTensor var = create_tensor<CLTensor>(obj.shape1, dt, 1, fixed_point_position); - CLTensor beta = create_tensor<CLTensor>(obj.shape1, dt, 1, fixed_point_position); - CLTensor gamma = create_tensor<CLTensor>(obj.shape1, dt, 1, fixed_point_position); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - BOOST_TEST(mean.info()->is_resizable()); - BOOST_TEST(var.info()->is_resizable()); - BOOST_TEST(beta.info()->is_resizable()); - BOOST_TEST(gamma.info()->is_resizable()); - - // Create and configure function - CLBatchNormalizationLayer norm; - norm.configure(&src, &dst, &mean, &var, &beta, &gamma, obj.epsilon); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(obj.shape0); - const ValidRegion valid_region_vec = shape_to_valid_region(obj.shape1); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - validate(mean.info()->valid_region(), valid_region_vec); - validate(var.info()->valid_region(), valid_region_vec); - validate(beta.info()->valid_region(), valid_region_vec); - validate(gamma.info()->valid_region(), valid_region_vec); -} - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(Random, - RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::F32), - obj, dt) -{ - // Compute function - CLTensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon); - - // Validate output - validate(CLAccessor(dst), ref_dst, tolerance_f, 0); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Quantized) - -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(Random, - RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::QS8) * boost::unit_test::data::xrange(1, 6), - obj, dt, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst, tolerance_qs8, 0); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_DATA_TEST_CASE(Random, - RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::QS16) * boost::unit_test::data::xrange(1, 14), - obj, dt, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst, tolerance_qs16, 0); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/BitwiseAnd.cpp b/tests/validation/CL/BitwiseAnd.cpp new file mode 100644 index 0000000000..3e458a4c9b --- /dev/null +++ b/tests/validation/CL/BitwiseAnd.cpp @@ -0,0 +1,94 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/functions/CLBitwiseAnd.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/BitwiseAndFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(CL) +TEST_SUITE(BitwiseAnd) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + CLTensor src1 = create_tensor<CLTensor>(shape, data_type); + CLTensor src2 = create_tensor<CLTensor>(shape, data_type); + CLTensor dst = create_tensor<CLTensor>(shape, data_type); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLBitwiseAnd bitwise_and; + bitwise_and.configure(&src1, &src2, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src1.info()->valid_region(), valid_region); + validate(src2.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src1.info()->padding(), padding); + validate(src2.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using CLBitwiseAndFixture = BitwiseAndValidationFixture<CLTensor, CLAccessor, CLBitwiseAnd, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, CLBitwiseAndFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLBitwiseAndFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/BitwiseNot.cpp b/tests/validation/CL/BitwiseNot.cpp new file mode 100644 index 0000000000..376bde9c78 --- /dev/null +++ b/tests/validation/CL/BitwiseNot.cpp @@ -0,0 +1,90 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/functions/CLBitwiseNot.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/BitwiseNotFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(CL) +TEST_SUITE(BitwiseNot) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + CLTensor src = create_tensor<CLTensor>(shape, data_type); + CLTensor dst = create_tensor<CLTensor>(shape, data_type); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLBitwiseNot bitwise_not; + bitwise_not.configure(&src, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using CLBitwiseNotFixture = BitwiseNotValidationFixture<CLTensor, CLAccessor, CLBitwiseNot, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, CLBitwiseNotFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLBitwiseNotFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/BitwiseOr.cpp b/tests/validation/CL/BitwiseOr.cpp new file mode 100644 index 0000000000..ecff0be6c0 --- /dev/null +++ b/tests/validation/CL/BitwiseOr.cpp @@ -0,0 +1,94 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/functions/CLBitwiseOr.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/BitwiseOrFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(CL) +TEST_SUITE(BitwiseOr) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + CLTensor src1 = create_tensor<CLTensor>(shape, data_type); + CLTensor src2 = create_tensor<CLTensor>(shape, data_type); + CLTensor dst = create_tensor<CLTensor>(shape, data_type); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLBitwiseOr bitwise_or; + bitwise_or.configure(&src1, &src2, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src1.info()->valid_region(), valid_region); + validate(src2.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src1.info()->padding(), padding); + validate(src2.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using CLBitwiseOrFixture = BitwiseOrValidationFixture<CLTensor, CLAccessor, CLBitwiseOr, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, CLBitwiseOrFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLBitwiseOrFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/BitwiseXor.cpp b/tests/validation/CL/BitwiseXor.cpp new file mode 100644 index 0000000000..3104894c29 --- /dev/null +++ b/tests/validation/CL/BitwiseXor.cpp @@ -0,0 +1,94 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/functions/CLBitwiseXor.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/BitwiseXorFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(CL) +TEST_SUITE(BitwiseXor) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + CLTensor src1 = create_tensor<CLTensor>(shape, data_type); + CLTensor src2 = create_tensor<CLTensor>(shape, data_type); + CLTensor dst = create_tensor<CLTensor>(shape, data_type); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLBitwiseXor bitwise_xor; + bitwise_xor.configure(&src1, &src2, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src1.info()->valid_region(), valid_region); + validate(src2.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src1.info()->padding(), padding); + validate(src2.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using CLBitwiseXorFixture = BitwiseXorValidationFixture<CLTensor, CLAccessor, CLBitwiseXor, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, CLBitwiseXorFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLBitwiseXorFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/Box3x3.cpp b/tests/validation/CL/Box3x3.cpp deleted file mode 100644 index f2df5e6511..0000000000 --- a/tests/validation/CL/Box3x3.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLBox3x3.h" - -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 3; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute CL box3x3 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor. - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT. - * - * @return Computed output tensor. - */ -CLTensor compute_box3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - // Create and configure function - CLBox3x3 box3x3; - box3x3.configure(&src, &dst, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - box3x3.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(Box3x3) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLBox3x3 box3x3; - box3x3.configure(&src, &dst, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - validate(src.info()->valid_region(), src_valid_region); - validate(dst.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - calculator.set_border_size(1); - calculator.set_border_mode(border_mode); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-1); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - CLTensor dst = compute_box3x3(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_box3x3(shape, border_mode, border_value); - - // Validate output - validate(CLAccessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - CLTensor dst = compute_box3x3(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_box3x3(shape, border_mode, border_value); - - // Validate output - validate(CLAccessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/CMakeLists.txt b/tests/validation/CL/CMakeLists.txt deleted file mode 100644 index f4477f621f..0000000000 --- a/tests/validation/CL/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# 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. -cmake_minimum_required (VERSION 3.1) - -include_directories(${CMAKE_SOURCE_DIR}/../include) - -set(arm_compute_test_validation_OPENCL_SOURCE_FILES - ${CMAKE_SOURCE_DIR}/CL/CLAccessor.h - ${CMAKE_CURRENT_SOURCE_DIR}/CLFixture.h - ${CMAKE_CURRENT_SOURCE_DIR}/CLFixture.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ActivationLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/BitwiseAnd.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Box3x3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ConvolutionLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/DepthConvert.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/FillBorder.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/FixedPoint/FixedPoint_QS8.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/FullyConnectedLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Gaussian3x3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Gaussian5x5.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/GEMM.cpp -` ${CMAKE_CURRENT_SOURCE_DIR}/IntegralImage.cpp -` ${CMAKE_CURRENT_SOURCE_DIR}/NonLinearFilter.cpp -` ${CMAKE_CURRENT_SOURCE_DIR}/PoolingLayer.cpp -` ${CMAKE_CURRENT_SOURCE_DIR}/ROIPoolingLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Sobel3x3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Sobel5x5.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/SoftmaxLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Threshold.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/DirectConvolutionLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/MeanStdDev.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/HarrisCorners.cpp -) - -add_library(arm_compute_test_validation_OPENCL OBJECT - ${arm_compute_test_validation_OPENCL_SOURCE_FILES} -) - -set(arm_compute_test_validation_TARGET_OBJECTS - ${arm_compute_test_validation_TARGET_OBJECTS} - $<TARGET_OBJECTS:arm_compute_test_validation_OPENCL> - PARENT_SCOPE -) - -set(arm_compute_test_validation_TARGET_LIBRARIES - ${arm_compute_test_validation_TARGET_LIBRARIES} - OpenCL - PARENT_SCOPE -) diff --git a/tests/validation/CL/ConvolutionLayer.cpp b/tests/validation/CL/ConvolutionLayer.cpp new file mode 100644 index 0000000000..d7123842e9 --- /dev/null +++ b/tests/validation/CL/ConvolutionLayer.cpp @@ -0,0 +1,186 @@ +/* + * 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 CONCLCTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLConvolutionLayer.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/LargeConvolutionLayerDataset.h" +#include "tests/datasets/SmallConvolutionLayerDataset.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ConvolutionLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F32 */ +constexpr AbsoluteTolerance<float> tolerance_f16(0.1f); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F16 */ +constexpr AbsoluteTolerance<float> tolerance_q(1.0f); /**< Tolerance value for comparing reference's output against implementation's output for fixed point data types */ + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ + DataType::F16, + DataType::F32, + DataType::QS8, + DataType::QS16, +}); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(ConvolutionLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(framework::dataset::concat(datasets::SmallConvolutionLayerDataset(), datasets::LargeConvolutionLayerDataset()), CNNDataTypes), + input_shape, weights_shape, bias_shape, output_shape, info, data_type) +{ + // Set fixed point position data type allowed + int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + // Create tensors + CLTensor src = create_tensor<CLTensor>(input_shape, data_type, 1, fixed_point_position); + CLTensor weights = create_tensor<CLTensor>(weights_shape, data_type, 1, fixed_point_position); + CLTensor bias = create_tensor<CLTensor>(bias_shape, data_type, 1, fixed_point_position); + CLTensor dst = create_tensor<CLTensor>(output_shape, data_type, 1, fixed_point_position); + + 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 + CLConvolutionLayer conv; + conv.configure(&src, &weights, &bias, &dst, info); + + // 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? +} + +template <typename T> +using CLConvolutionLayerFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLConvolutionLayer, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using CLConvolutionLayerFixedPointFixture = ConvolutionValidationFixedPointFixture<CLTensor, CLAccessor, CLConvolutionLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// We test for fixed point precision [4,6] +FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 4, 7))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_q); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 4, 7))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_q); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) +FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_q); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_q); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/DepthConcatenateLayer.cpp b/tests/validation/CL/DepthConcatenateLayer.cpp new file mode 100644 index 0000000000..a8ef1c37c7 --- /dev/null +++ b/tests/validation/CL/DepthConcatenateLayer.cpp @@ -0,0 +1,123 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLDepthConcatenate.h" +#include "tests/CL/CLAccessor.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/DepthConcatenateLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(CL) +TEST_SUITE(DepthConcatenateLayer) + +//TODO(COMPMID-415): Add configuration test? + +template <typename T> +using CLDepthConcatenateLayerFixture = DepthConcatenateValidationFixture<CLTensor, CLAccessor, CLDepthConcatenate, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLDepthConcatenateLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLDepthConcatenateLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +TEST_SUITE_END() + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLDepthConcatenateLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLDepthConcatenateLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +FIXTURE_DATA_TEST_CASE(RunSmall, CLDepthConcatenateLayerFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), + framework::dataset::make("DataType", + DataType::QS8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLDepthConcatenateLayerFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), + framework::dataset::make("DataType", + DataType::QS8))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLDepthConcatenateLayerFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), + framework::dataset::make("DataType", + DataType::QS16))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLDepthConcatenateLayerFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), + framework::dataset::make("DataType", + DataType::QS16))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/DepthConvert.cpp b/tests/validation/CL/DepthConvert.cpp deleted file mode 100644 index 57a21e89c7..0000000000 --- a/tests/validation/CL/DepthConvert.cpp +++ /dev/null @@ -1,495 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.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/CL/functions/CLDepthConvert.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::validation; - -namespace -{ -/** Compute CL depth convert function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in Data type of input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Conversion policy. - * @param[in] shift Value for down/up conversions. Must be 0 <= shift < 8. - * - * @return Computed output CLtensor. - */ -CLTensor compute_depth_convert(const TensorShape &shape, DataType dt_in, DataType dt_out, ConvertPolicy policy, uint32_t shift, uint32_t fixed_point_position = 0) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, dt_in, 1, fixed_point_position); - CLTensor dst = create_tensor<CLTensor>(shape, dt_out, 1, fixed_point_position); - - // Create and configure function - CLDepthConvert depth_convert; - depth_convert.configure(&src, &dst, policy, shift); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - depth_convert.run(); - - return dst; -} -/** Configure and validate region/padding function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in Data type of input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Conversion policy. - * @param[in] shift Value for down/up conversions. Must be 0 <= shift < 8. - * @param[in] fixed_point_position Fixed point position. - * - */ -void compute_configure_validate(const TensorShape &shape, DataType dt_in, DataType dt_out, ConvertPolicy policy, uint32_t shift, uint32_t fixed_point_position = 0) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, dt_in, 1, fixed_point_position); - CLTensor dst = create_tensor<CLTensor>(shape, dt_out, 1, fixed_point_position); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLDepthConvert depth_convert; - depth_convert.configure(&src, &dst, policy, shift); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(DepthConvert) - -BOOST_AUTO_TEST_SUITE(U8_to_U16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U8, DataType::U16, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U8, DataType::U16, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::U16, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U8, DataType::U16, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::U16, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U8_to_S16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U8, DataType::S16, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U8, DataType::S16, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::S16, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U8, DataType::S16, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::S16, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U8_to_S32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U8, DataType::S32, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U8, DataType::S32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::S32, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U8, DataType::S32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::S32, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U16_to_U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U16, DataType::U8, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U16, DataType::U8, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U16, DataType::U8, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U16, DataType::U8, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U16, DataType::U8, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U16_to_U32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U16, DataType::U32, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U16, DataType::U32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U16, DataType::U32, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::U16, DataType::U32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U16, DataType::U32, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16_to_U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::S16, DataType::U8, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::S16, DataType::U8, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::S16, DataType::U8, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::S16, DataType::U8, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::S16, DataType::U8, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16_to_S32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::S16, DataType::S32, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::S16, DataType::S32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::S16, DataType::S32, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::S16, DataType::S32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::S16, DataType::S32, policy, shift, 0); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Quantized_to_F32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::QS8, DataType::QS16 }) - * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) * boost::unit_test::data::xrange(1, 7, 1), - shape, dt, policy, fixed_point_position) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, dt, DataType::F32, policy, 0, fixed_point_position); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::make({ DataType::QS8, DataType::QS16 }) * boost::unit_test::data::xrange(1, 7, 1), - shape, policy, dt, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, dt, DataType::F32, policy, 0, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, dt, DataType::F32, policy, 0, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::QS8, DataType::QS16 }) - * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) * boost::unit_test::data::xrange(1, 7, 1), - shape, dt, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, dt, DataType::F32, policy, 0, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, dt, DataType::F32, policy, 0, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(F32_to_Quantized) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::QS8, DataType::QS16 }) - * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) * boost::unit_test::data::xrange(1, 7, 1), - shape, dt, policy, fixed_point_position) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::F32, dt, policy, 0, fixed_point_position); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::QS8, DataType::QS16 }) - * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) * boost::unit_test::data::xrange(1, 7, 1), - shape, dt, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::F32, dt, policy, 0, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::F32, dt, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::QS8, DataType::QS16 }) - * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) * boost::unit_test::data::xrange(1, 7, 1), - shape, dt, policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_depth_convert(shape, DataType::F32, dt, policy, 0, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::F32, dt, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/DepthwiseConvolution.cpp b/tests/validation/CL/DepthwiseConvolution.cpp new file mode 100644 index 0000000000..ccee9607d3 --- /dev/null +++ b/tests/validation/CL/DepthwiseConvolution.cpp @@ -0,0 +1,69 @@ +/* + * 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 CONCLCTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLDepthwiseConvolution.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/LargeDepthwiseConvolutionDataset.h" +#include "tests/datasets/SmallDepthwiseConvolutionDataset.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/DepthwiseConvolutionFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F32 */ +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(DepthwiseConvolution) + +template <typename T> +using CLDepthwiseConvolutionFixture = DepthwiseConvolutionValidationFixture<CLTensor, CLAccessor, CLDepthwiseConvolution, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, CLDepthwiseConvolutionFixture<float>, framework::DatasetMode::PRECOMMIT, datasets::SmallDepthwiseConvolutionDataset()) +{ + validate(CLAccessor(_target), _reference, tolerance_f32); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, CLDepthwiseConvolutionFixture<float>, framework::DatasetMode::NIGHTLY, datasets::LargeDepthwiseConvolutionDataset()) +{ + validate(CLAccessor(_target), _reference, tolerance_f32); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/DepthwiseSeparableConvolutionLayer.cpp b/tests/validation/CL/DepthwiseSeparableConvolutionLayer.cpp new file mode 100644 index 0000000000..4fac9b2d0d --- /dev/null +++ b/tests/validation/CL/DepthwiseSeparableConvolutionLayer.cpp @@ -0,0 +1,64 @@ +/* + * 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 CONCLCTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLDepthwiseSeparableConvolutionLayer.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/MobileNetDepthwiseSeparableConvolutionLayerDataset.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/DepthwiseSeparableConvolutionLayerFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F32 */ +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(DepthwiseSeparableConvolutionLayer) + +// Configuration test to do + +template <typename T> +using CLDepthwiseSeparableConvolutionLayerFixture = DepthwiseSeparableConvolutionValidationFixture<CLTensor, CLAccessor, CLDepthwiseSeparableConvolutionLayer, T>; +FIXTURE_DATA_TEST_CASE(RunSmall, CLDepthwiseSeparableConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, datasets::MobileNetDepthwiseSeparableConvolutionLayerDataset()) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/DirectConvolutionLayer.cpp b/tests/validation/CL/DirectConvolutionLayer.cpp new file mode 100644 index 0000000000..d2d2cd1419 --- /dev/null +++ b/tests/validation/CL/DirectConvolutionLayer.cpp @@ -0,0 +1,129 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLDirectConvolutionLayer.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/DirectConvolutionLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr AbsoluteTolerance<float> tolerance_fp16(0.1f); /**< Tolerance for floating point tests */ +constexpr AbsoluteTolerance<float> tolerance_fp32(0.001f); /**< Tolerance for floating point tests */ + +constexpr AbsoluteTolerance<int8_t> tolerance_qs8(0); /**< Tolerance for fixed point tests */ +constexpr AbsoluteTolerance<int16_t> tolerance_qs16(0); /**< Tolerance for fixed point tests */ + +/** Direct convolution data set. */ +const auto data_quantized = combine(datasets::SmallDirectConvolutionShapes(), + combine(framework::dataset::make("StrideX", 1, 3), + combine(framework::dataset::make("StrideY", 1, 3), + combine(concat(combine(framework::dataset::make("PadX", 0), + combine(framework::dataset::make("PadY", 0), + framework::dataset::make("KernelSize", 1))), + combine(framework::dataset::make("PadX", 0, 2), + combine(framework::dataset::make("PadY", 0, 2), + framework::dataset::make("KernelSize", { 3 })))), + framework::dataset::make("NumKernels", { 1, 4, 8, 16 }))))); + +const auto data = combine(datasets::SmallDirectConvolutionShapes(), + combine(framework::dataset::make("StrideX", 1, 3), + combine(framework::dataset::make("StrideY", 1, 3), + combine(concat(combine(framework::dataset::make("PadX", 0), + combine(framework::dataset::make("PadY", 0), + framework::dataset::make("KernelSize", 1))), + combine(framework::dataset::make("PadX", 0, 2), + combine(framework::dataset::make("PadY", 0, 2), + framework::dataset::make("KernelSize", { 3, 5 })))), + framework::dataset::make("NumKernels", { 1, 4, 8, 16 }))))); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(DirectConvolutionLayer) + +//TODO(COMPMID-415): Configuration tests? + +template <typename T> +using CLDirectConvolutionLayerFixture = DirectConvolutionValidationFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(Run, CLDirectConvolutionLayerFixture<half_float::half>, framework::DatasetMode::ALL, combine(data, framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fp16); +} +TEST_SUITE_END() + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(Run, CLDirectConvolutionLayerFixture<float>, framework::DatasetMode::ALL, combine(data, framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fp32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using CLDirectConvolutionLayerFixedPointFixture = DirectConvolutionValidationFixedPointFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +FIXTURE_DATA_TEST_CASE(Run, CLDirectConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(data_quantized, framework::dataset::make("DataType", DataType::QS8)), + framework::dataset::make("FractionalBits", 2, 7))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs8); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +FIXTURE_DATA_TEST_CASE(Run, CLDirectConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::ALL, combine(combine(data_quantized, framework::dataset::make("DataType", DataType::QS16)), + framework::dataset::make("FractionalBits", 2, 15))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs16); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/FillBorder.cpp b/tests/validation/CL/FillBorder.cpp deleted file mode 100644 index dc522c5c3b..0000000000 --- a/tests/validation/CL/FillBorder.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Validation.h" - -#include "arm_compute/core/CL/kernels/CLFillBorderKernel.h" -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLScheduler.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" - -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(FillBorder, BorderModes() * boost::unit_test::data::make({ PaddingSize{ 0 }, PaddingSize{ 1, 0, 1, 2 }, PaddingSize{ 10 } }), border_mode, padding) -{ - constexpr uint8_t border_value = 42U; - constexpr uint8_t tensor_value = 89U; - BorderSize border_size{ 5 }; - - // Create tensors - CLTensor src = create_tensor<CLTensor>(TensorShape{ 10U, 10U, 2U }, DataType::U8); - - src.info()->extend_padding(padding); - - // Allocate tensor - src.allocator()->allocate(); - - // Check padding is as required - validate(src.info()->padding(), padding); - - // Fill tensor with constant value - std::uniform_int_distribution<uint8_t> distribution{ tensor_value, tensor_value }; - library->fill(CLAccessor(src), distribution, 0); - - // Create and configure kernel - CLFillBorderKernel fill_border; - fill_border.configure(&src, border_size, border_mode, border_value); - - // Run kernel - fill_border.run(fill_border.window(), CLScheduler::get().queue()); - - // Validate border - border_size.limit(padding); - validate(CLAccessor(src), border_size, border_mode, &border_value); - - // Validate tensor - validate(CLAccessor(src), &tensor_value); -} - -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/FixedPoint/FixedPoint_QS8.cpp b/tests/validation/CL/FixedPoint/FixedPoint_QS8.cpp deleted file mode 100644 index d4ccc2ba2b..0000000000 --- a/tests/validation/CL/FixedPoint/FixedPoint_QS8.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" - -#include "arm_compute/core/CL/CLKernelLibrary.h" -#include "arm_compute/core/CL/ICLKernel.h" -#include "arm_compute/core/CL/OpenCL.h" -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/core/Window.h" -#include "arm_compute/runtime/CL/CLScheduler.h" -#include "arm_compute/runtime/CL/CLSubTensor.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" - -#include "arm_compute/core/CL/ICLTensor.h" - -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -const float tolerance_exp = 1.0f; /**< Tolerance value for comparing reference's output against implementation's output (exponential)*/ -const float tolerance_invsqrt = 4.0f; /**< Tolerance value for comparing reference's output against implementation's output (inverse square-root) */ -const float tolerance_log = 5.0f; /**< Tolerance value for comparing reference's output against implementation's output (logarithm) */ - -/** Compute Neon fixed point operation for signed 8bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -CLTensor compute_fixed_point_op(const TensorShape &shape, int fixed_point_position, FixedPointOp op) -{ - std::string fixed_point_operation_kernel; -#ifndef EMBEDDED_KERNELS - fixed_point_operation_kernel += "#include \"fixed_point.h\"\n"; -#endif /* EMBEDDED_KERNELS */ - fixed_point_operation_kernel += - "__kernel void fixed_point_operation_qs8( \n" - " __global char* src, \n" - " __global char* dst) \n" - "{ \n" - " char16 in = vload16(0, src + get_global_id(0) * 16); \n" - " if(FIXED_POINT_OP == 0) \n" - " { \n" - " vstore16(EXP_OP_EXPAND(in, DATA_TYPE, 16, FIXED_POINT_POS), 0, dst + get_global_id(0) * 16); \n" - " } \n" - " else if(FIXED_POINT_OP == 1) \n" - " { \n" - " vstore16(INVSQRT_OP_EXPAND(in, DATA_TYPE, 16, FIXED_POINT_POS), 0, dst + get_global_id(0) * 16); \n" - " } \n" - " else \n" - " { \n" - " vstore16(LOG_OP_EXPAND(in, DATA_TYPE, 16, FIXED_POINT_POS), 0, dst + get_global_id(0) * 16); \n" - " } \n" - "} \n" - "\n"; - - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::QS8, 1, fixed_point_position); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::QS8, 1, fixed_point_position); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Set build options - std::string build_opts = "-DFIXED_POINT_POS=" + support::cpp11::to_string(fixed_point_position); - build_opts += " -DDATA_TYPE=qs8"; - - // Fill tensors. - int min = 0; - int max = 0; - switch(op) - { - case FixedPointOp::EXP: - min = -(1 << (fixed_point_position - 1)); - max = (1 << (fixed_point_position - 1)); - build_opts += " -DFIXED_POINT_OP=0"; - break; - case FixedPointOp::INV_SQRT: - min = 1; - max = 0x7F; - build_opts += " -DFIXED_POINT_OP=1"; - break; - case FixedPointOp::LOG: - min = (1 << (fixed_point_position - 1)); - max = 0x3F; - build_opts += " -DFIXED_POINT_OP=2"; - break; - default: - ARM_COMPUTE_ERROR("Operation not supported"); - } - - std::uniform_int_distribution<> distribution(min, max); - library->fill(CLAccessor(src), distribution, 0); - - std::vector<std::string> sources; - -#ifndef EMBEDDED_KERNELS - build_opts += " -I" + CLKernelLibrary::get().get_kernel_path(); -#else /* EMBEDDED_KERNELS */ - sources.push_back(CLKernelLibrary::get().get_program_source("fixed_point.h")); -#endif /* EMBEDDED_KERNELS */ - - sources.push_back(fixed_point_operation_kernel); - - // Create program - ::cl::Program program(sources); - - // Build program - program.build(build_opts.c_str()); - - ::cl::Kernel kernel(program, "fixed_point_operation_qs8", nullptr); - - unsigned int idx = 0; - kernel.setArg(idx++, src.cl_buffer()); - kernel.setArg(idx++, dst.cl_buffer()); - - ::cl::NDRange gws(shape[0] / 16, 1, 1); - CLScheduler::get().queue().enqueueNDRangeKernel(kernel, 0, gws); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS8) - -BOOST_AUTO_TEST_SUITE(Exp) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(1, 6), shape, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_fixed_point_op(shape, fixed_point_position, FixedPointOp::EXP); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS8, DataType::QS8, FixedPointOp::EXP, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst, tolerance_exp); -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Log) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(3, 6), shape, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_fixed_point_op(shape, fixed_point_position, FixedPointOp::LOG); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS8, DataType::QS8, FixedPointOp::LOG, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst, tolerance_log); -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Invsqrt) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(1, 6), shape, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_fixed_point_op(shape, fixed_point_position, FixedPointOp::INV_SQRT); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS8, DataType::QS8, FixedPointOp::INV_SQRT, fixed_point_position); - - // Validate output - validate(CLAccessor(dst), ref_dst, tolerance_invsqrt); -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/Floor.cpp b/tests/validation/CL/Floor.cpp new file mode 100644 index 0000000000..81495e8337 --- /dev/null +++ b/tests/validation/CL/Floor.cpp @@ -0,0 +1,66 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLFloor.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/FloorFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(CL) +TEST_SUITE(Floor) + +template <typename T> +using CLFloorFixture = FloorValidationFixture<CLTensor, CLAccessor, CLFloor, T>; + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLFloorFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLFloorFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/FullyConnectedLayer.cpp b/tests/validation/CL/FullyConnectedLayer.cpp new file mode 100644 index 0000000000..7a8734b5a3 --- /dev/null +++ b/tests/validation/CL/FullyConnectedLayer.cpp @@ -0,0 +1,195 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/FullyConnectedLayerDataset.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/FullyConnectedLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); +constexpr AbsoluteTolerance<float> tolerance_f16(0.4f); +/** Tolerance for fixed point operations */ +constexpr AbsoluteTolerance<float> tolerance_fixed_point(1.f); + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ + DataType::F16, + DataType::F32, + DataType::QS8, + DataType::QS16, +}); + +const auto FullyConnectedParameters = combine(framework::dataset::make("TransposeWeights", { false, true }), framework::dataset::make("ReshapeWeights", { false, true })); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(FullyConnectedLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(framework::dataset::concat(datasets::SmallFullyConnectedLayerDataset(), datasets::LargeFullyConnectedLayerDataset()), + FullyConnectedParameters), + CNNDataTypes), + src_shape, weights_shape, bias_shape, dst_shape, transpose_weights, reshape_weights, data_type) +{ + // Set fixed point position data type allowed + int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + TensorShape ws(weights_shape); + + // Transpose weights if not done in the function + if(!reshape_weights || !transpose_weights) + { + const size_t shape_x = ws.x(); + ws.set(0, ws.y()); + ws.set(1, shape_x); + } + + // Create tensors + CLTensor src = create_tensor<CLTensor>(src_shape, data_type, 1, fixed_point_position); + CLTensor weights = create_tensor<CLTensor>(ws, data_type, 1, fixed_point_position); + CLTensor bias = create_tensor<CLTensor>(bias_shape, data_type, 1, fixed_point_position); + CLTensor dst = create_tensor<CLTensor>(dst_shape, data_type, 1, fixed_point_position); + + 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. + CLFullyConnectedLayer fc; + fc.configure(&src, &weights, &bias, &dst, transpose_weights, !reshape_weights); + + // Validate valid region + const ValidRegion dst_valid_region = shape_to_valid_region(dst_shape); + validate(dst.info()->valid_region(), dst_valid_region); +} + +template <typename T> +using CLFullyConnectedLayerFixture = FullyConnectedLayerValidationFixture<CLTensor, CLAccessor, CLFullyConnectedLayer, T, false>; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLFullyConnectedLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLFullyConnectedLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLFullyConnectedLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallFullyConnectedLayerDataset(), FullyConnectedParameters), + framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLFullyConnectedLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeFullyConnectedLayerDataset(), FullyConnectedParameters), + framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using CLFullyConnectedLayerFixedPointFixture = FullyConnectedLayerValidationFixedPointFixture<CLTensor, CLAccessor, CLFullyConnectedLayer, T, false>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// Testing for fixed point position [1,6) as reciprocal limits the maximum fixed point position to 5 +FIXTURE_DATA_TEST_CASE(RunSmall, CLFullyConnectedLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fixed_point); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLFullyConnectedLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fixed_point); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14 +FIXTURE_DATA_TEST_CASE(RunSmall, CLFullyConnectedLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fixed_point); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLFullyConnectedLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fixed_point); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/GEMM.cpp b/tests/validation/CL/GEMM.cpp new file mode 100644 index 0000000000..6b2b2b41b1 --- /dev/null +++ b/tests/validation/CL/GEMM.cpp @@ -0,0 +1,167 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLGEMM.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/LargeGEMMDataset.h" +#include "tests/datasets/SmallGEMMDataset.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/GEMMFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for floating point data types */ +constexpr AbsoluteTolerance<float> tolerance_f16(0.1f); /**< Tolerance value for comparing reference's output against implementation's output for floating point data types */ +constexpr AbsoluteTolerance<float> tolerance_q(1.0f); /**< Tolerance value for comparing reference's output against implementation's output for fixed point data types */ + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ + DataType::F16, + DataType::F32, + DataType::QS8, + DataType::QS16, +}); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(GEMM) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(framework::dataset::concat(datasets::SmallGEMMDataset(), datasets::LargeGEMMDataset()), CNNDataTypes), + shape_a, shape_b, shape_c, output_shape, alpha, beta, data_type) +{ + // Set fixed point position data type allowed + const int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + // Create tensors + CLTensor a = create_tensor<CLTensor>(shape_a, data_type, 1, fixed_point_position); + CLTensor b = create_tensor<CLTensor>(shape_b, data_type, 1, fixed_point_position); + CLTensor c = create_tensor<CLTensor>(shape_c, data_type, 1, fixed_point_position); + CLTensor dst = create_tensor<CLTensor>(output_shape, data_type, 1, fixed_point_position); + + ARM_COMPUTE_EXPECT(a.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(b.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(c.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLGEMM gemm; + gemm.configure(&a, &b, &c, &dst, alpha, beta); + + //TODO(COMPMID-415): Validate valid region +} + +template <typename T> +using CLGEMMFixture = GEMMValidationFixture<CLTensor, CLAccessor, CLGEMM, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallGEMMDataset(), framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeGEMMDataset(), framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallGEMMDataset(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeGEMMDataset(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using CLGEMMFixedPointFixture = GEMMValidationFixedPointFixture<CLTensor, CLAccessor, CLGEMM, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallGEMMDataset(), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 7))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_q); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeGEMMDataset(), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 7))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_q); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallGEMMDataset(), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_q); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeGEMMDataset(), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_q); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/Gaussian3x3.cpp b/tests/validation/CL/Gaussian3x3.cpp deleted file mode 100644 index 2ef077c005..0000000000 --- a/tests/validation/CL/Gaussian3x3.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLGaussian3x3.h" - -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 3; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute CL gaussian3x3 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor. - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT. - * - * @return Computed output tensor. - */ -CLTensor compute_gaussian3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - // Create and configure function - CLGaussian3x3 gaussian3x3; - gaussian3x3.configure(&src, &dst, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - gaussian3x3.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(Gaussian3x3) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLGaussian3x3 gaussian3x3; - gaussian3x3.configure(&src, &dst, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - validate(src.info()->valid_region(), src_valid_region); - validate(dst.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - calculator.set_border_size(1); - calculator.set_border_mode(border_mode); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-1); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - CLTensor dst = compute_gaussian3x3(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_gaussian3x3(shape, border_mode, border_value); - - // Validate output - validate(CLAccessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - CLTensor dst = compute_gaussian3x3(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_gaussian3x3(shape, border_mode, border_value); - - // Validate output - validate(CLAccessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/Gaussian5x5.cpp b/tests/validation/CL/Gaussian5x5.cpp deleted file mode 100644 index fb21ed06af..0000000000 --- a/tests/validation/CL/Gaussian5x5.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLGaussian5x5.h" - -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 5; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute CL gaussian5x5 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor. - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT. - * - * @return Computed output tensor. - */ -CLTensor compute_gaussian5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - // Create and configure function - CLGaussian5x5 gaussian5x5; - gaussian5x5.configure(&src, &dst, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - gaussian5x5.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(Gaussian5x5) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLGaussian5x5 gaussian5x5; - gaussian5x5.configure(&src, &dst, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - validate(src.info()->valid_region(), src_valid_region); - validate(dst.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - calculator.set_border_size(2); - calculator.set_border_mode(border_mode); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-2); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - CLTensor dst = compute_gaussian5x5(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_gaussian5x5(shape, border_mode, border_value); - - // Validate output - validate(CLAccessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - CLTensor dst = compute_gaussian5x5(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_gaussian5x5(shape, border_mode, border_value); - - // Validate output - validate(CLAccessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/HarrisCorners.cpp b/tests/validation/CL/HarrisCorners.cpp deleted file mode 100644 index 6370c4d972..0000000000 --- a/tests/validation/CL/HarrisCorners.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLArray.h" -#include "arm_compute/runtime/CL/functions/CLHarrisCorners.h" -#include "arm_compute/runtime/Tensor.h" -#include "arm_compute/runtime/TensorAllocator.h" - -#include "PaddingCalculator.h" -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -/** Compute CL Harris corners function. - * - * @param[in] shape Shape of input tensor - * @param[in] threshold Minimum threshold with which to eliminate Harris Corner scores (computed using the normalized Sobel kernel). - * @param[in] min_dist Radial Euclidean distance for the euclidean distance stage - * @param[in] sensitivity Sensitivity threshold k from the Harris-Stephens equation - * @param[in] gradient_size The gradient window size to use on the input. The implementation supports 3, 5, and 7 - * @param[in] block_size The block window size used to compute the Harris Corner score. The implementation supports 3, 5, and 7. - * @param[in] border_mode Border mode to use - * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT. - * - * @return Computed corners' keypoints. - */ -void compute_harris_corners(const TensorShape &shape, CLKeyPointArray &corners, float threshold, float min_dist, float sensitivity, - int32_t gradient_size, int32_t block_size, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - src.info()->set_format(Format::U8); - - // Create harris corners configure function - CLHarrisCorners harris_corners; - harris_corners.configure(&src, threshold, min_dist, sensitivity, gradient_size, block_size, &corners, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - harris_corners.run(); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(HarrisCorners) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (Small2DShapes() + Large2DShapes()) * BorderModes() - * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }), - shape, border_mode, gradient, block) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - src.info()->set_format(Format::U8); - - CLKeyPointArray corners(shape.total_size()); - - uint8_t constant_border_value = 0; - - std::mt19937 gen(user_config.seed.get()); - std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min()); - - const float threshold = real_dist(gen); - const float sensitivity = real_dist(gen); - const float max_euclidean_distance = 30.f; - - real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance); - float min_dist = real_dist(gen); - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::uniform_int_distribution<uint8_t> int_dist(0, 255); - constant_border_value = int_dist(gen); - } - - BOOST_TEST(src.info()->is_resizable()); - - // Create harris corners configure function - CLHarrisCorners harris_corners; - harris_corners.configure(&src, threshold, min_dist, sensitivity, gradient, block, &corners, border_mode, constant_border_value); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - - validate(src.info()->valid_region(), valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - - calculator.set_border_mode(border_mode); - calculator.set_border_size(gradient / 2); - calculator.set_access_offset(-gradient / 2); - calculator.set_accessed_elements(16); - - const PaddingSize padding = calculator.required_padding(); - - validate(src.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes() * BorderModes() * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }), shape, border_mode, gradient, block) -{ - uint8_t constant_border_value = 0; - - std::mt19937 gen(user_config.seed.get()); - std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min()); - - const float threshold = real_dist(gen); - const float sensitivity = real_dist(gen); - const float max_euclidean_distance = 30.f; - - real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance); - const float min_dist = real_dist(gen); - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::uniform_int_distribution<uint8_t> int_dist(0, 255); - constant_border_value = int_dist(gen); - } - - // Create array of keypoints - CLKeyPointArray dst(shape.total_size()); - - // Compute function - compute_harris_corners(shape, dst, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value); - - // Compute reference - KeyPointArray ref_dst = Reference::compute_reference_harris_corners(shape, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value); - - // Validate output - dst.map(); - validate(dst, ref_dst, 1); - dst.unmap(); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, Large2DShapes() * BorderModes() * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }), shape, border_mode, gradient, block) -{ - uint8_t constant_border_value = 0; - - std::mt19937 gen(user_config.seed.get()); - std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min()); - - const float threshold = real_dist(gen); - const float sensitivity = real_dist(gen); - const float max_euclidean_distance = 30.f; - - real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance); - const float min_dist = real_dist(gen); - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::uniform_int_distribution<uint8_t> int_dist(0, 255); - constant_border_value = int_dist(gen); - } - - // Create array of keypoints - CLKeyPointArray dst(shape.total_size()); - - // Compute function - compute_harris_corners(shape, dst, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value); - - // Compute reference - KeyPointArray ref_dst = Reference::compute_reference_harris_corners(shape, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value); - - // Validate output - dst.map(); - validate(dst, ref_dst); - dst.unmap(); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/IntegralImage.cpp b/tests/validation/CL/IntegralImage.cpp deleted file mode 100644 index dc325a1f8a..0000000000 --- a/tests/validation/CL/IntegralImage.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.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/CL/functions/CLIntegralImage.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::validation; - -namespace -{ -/** Compute CL integral image function. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -CLTensor compute_integral_image(const TensorShape &shape) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U32); - - // Create integral image configure function - CLIntegralImage integral_image; - integral_image.configure(&src, &dst); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - integral_image.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(IntegralImage) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, SmallShapes() + LargeShapes(), shape) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U32); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create integral image configure function - CLIntegralImage integral_image; - integral_image.configure(&src, &dst); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - CLTensor dst = compute_integral_image(shape); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_integral_image(shape); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes(), shape) -{ - // Compute function - CLTensor dst = compute_integral_image(shape); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_integral_image(shape); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/L2Normalize.cpp b/tests/validation/CL/L2Normalize.cpp new file mode 100644 index 0000000000..bd9bf17322 --- /dev/null +++ b/tests/validation/CL/L2Normalize.cpp @@ -0,0 +1,78 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLL2Normalize.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/L2NormalizeFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr AbsoluteTolerance<float> tolerance_f32(0.00001f); + +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(L2Normalize) + +template <typename T> +using CLL2NormalizeFixture = L2NormalizeValidationFixture<CLTensor, CLAccessor, CLL2Normalize, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLL2NormalizeFixture<float>, framework::DatasetMode::PRECOMMIT, + combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("Axis", { 0 })), framework::dataset::make("Epsilon", { 1e-12 }))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLL2NormalizeFixture<float>, framework::DatasetMode::NIGHTLY, + combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("Axis", { 0 })), framework::dataset::make("Epsilon", { 1e-12 }))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/MeanStdDev.cpp b/tests/validation/CL/MeanStdDev.cpp new file mode 100644 index 0000000000..ff8a087c6b --- /dev/null +++ b/tests/validation/CL/MeanStdDev.cpp @@ -0,0 +1,97 @@ +/* + * 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 "arm_compute/runtime/CL/functions/CLMeanStdDev.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Macros.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/MeanStdDevFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr RelativeTolerance tolerance_rel_high_error(0.05f); +constexpr RelativeTolerance tolerance_rel_low_error(0.0005f); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(MeanStdDev) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + CLTensor src = create_tensor<CLTensor>(shape, data_type); + + // Create output variables + float mean = 0.f; + float std_dev = 0.f; + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create configure function + CLMeanStdDev 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 = PaddingCalculator(shape.x(), 8).required_padding(); + validate(src.info()->padding(), padding); +} + +template <typename T> +using CLMeanStdDevFixture = MeanStdDevValidationFixture<CLTensor, CLAccessor, CLMeanStdDev, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, CLMeanStdDevFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate mean output + validate(_target.first, _reference.first); + + // Validate std_dev output + validate(_target.second, _reference.second, tolerance_rel_high_error); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLMeanStdDevFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate mean output + validate(_target.first, _reference.first, tolerance_rel_low_error); + + // Validate std_dev output + validate(_target.second, _reference.second, tolerance_rel_high_error); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/MinMaxLocation.cpp b/tests/validation/CL/MinMaxLocation.cpp deleted file mode 100644 index 5f8be433cd..0000000000 --- a/tests/validation/CL/MinMaxLocation.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.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/CL/functions/CLMinMaxLocation.h" -#include "arm_compute/runtime/Tensor.h" -#include "arm_compute/runtime/TensorAllocator.h" - -#include "PaddingCalculator.h" -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -/** Compute CL MinMaxLocation function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in Data type of first input tensor. - * @param[out] min Minimum value of tensor - * @param[out] max Maximum value of tensor - * @param[out] min_loc Array with locations of minimum values - * @param[out] max_loc Array with locations of maximum values - * @param[out] min_count Number of minimum values found - * @param[out] max_count Number of maximum values found - * - * @return Computed output tensor. - */ -void compute_min_max_location(const TensorShape &shape, DataType dt_in, void *min, void *max, - CLCoordinates2DArray &min_loc, CLCoordinates2DArray &max_loc, uint32_t &min_count, uint32_t &max_count) -{ - // Create tensor - CLTensor src = create_tensor<CLTensor>(shape, dt_in); - - // Create and configure min_max_location configure function - CLMinMaxLocation min_max_loc; - min_max_loc.configure(&src, min, max, &min_loc, &max_loc, &min_count, &max_count); - - // Allocate tensors - src.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - min_max_loc.run(); -} - -void validate_configuration(const CLTensor &src, TensorShape shape) -{ - BOOST_TEST(src.info()->is_resizable()); - - // Create output storage - int32_t min; - int32_t max; - CLCoordinates2DArray min_loc(shape.total_size()); - CLCoordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - // Create and configure function - CLMinMaxLocation min_max_loc; - min_max_loc.configure(&src, &min, &max, &min_loc, &max_loc, &min_count, &max_count); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), src.info()->dimension(0)).required_padding(); - validate(src.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(MinMaxLocation) -BOOST_AUTO_TEST_SUITE(U8) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (Small2DShapes() + Large2DShapes()), - shape) -{ - // Create tensor - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - src.info()->set_format(Format::U8); - - validate_configuration(src, shape); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes(), - shape) -{ - // Create output storage - int32_t min; - int32_t max; - CLCoordinates2DArray min_loc(shape.total_size()); - CLCoordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - int32_t ref_min; - int32_t ref_max; - CLCoordinates2DArray ref_min_loc(shape.total_size()); - CLCoordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, DataType::U8, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - ref_min_loc.map(); - ref_max_loc.map(); - - Reference::compute_reference_min_max_location(shape, DataType::U8, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - min_loc.map(); - max_loc.map(); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); - - ref_min_loc.unmap(); - ref_max_loc.unmap(); - min_loc.unmap(); - max_loc.unmap(); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, Large2DShapes(), - shape) -{ - // Create output storage - int32_t min; - int32_t max; - CLCoordinates2DArray min_loc(shape.total_size()); - CLCoordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - int32_t ref_min; - int32_t ref_max; - CLCoordinates2DArray ref_min_loc(shape.total_size()); - CLCoordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, DataType::U8, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - ref_min_loc.map(); - ref_max_loc.map(); - - Reference::compute_reference_min_max_location(shape, DataType::U8, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - min_loc.map(); - max_loc.map(); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); - - ref_min_loc.unmap(); - ref_max_loc.unmap(); - min_loc.unmap(); - max_loc.unmap(); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (Small2DShapes() + Large2DShapes()), - shape) -{ - // Create tensor - CLTensor src = create_tensor<CLTensor>(shape, DataType::S16); - src.info()->set_format(Format::S16); - - validate_configuration(src, shape); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes(), - shape) -{ - // Create output storage - int32_t min; - int32_t max; - CLCoordinates2DArray min_loc(shape.total_size()); - CLCoordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - int32_t ref_min; - int32_t ref_max; - CLCoordinates2DArray ref_min_loc(shape.total_size()); - CLCoordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, DataType::S16, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - ref_min_loc.map(); - ref_max_loc.map(); - - Reference::compute_reference_min_max_location(shape, DataType::S16, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - min_loc.map(); - max_loc.map(); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); - - ref_min_loc.unmap(); - ref_max_loc.unmap(); - min_loc.unmap(); - max_loc.unmap(); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, Large2DShapes(), - shape) -{ - // Create output storage - int32_t min; - int32_t max; - CLCoordinates2DArray min_loc(shape.total_size()); - CLCoordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - int32_t ref_min; - int32_t ref_max; - CLCoordinates2DArray ref_min_loc(shape.total_size()); - CLCoordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, DataType::S16, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - ref_min_loc.map(); - ref_max_loc.map(); - - Reference::compute_reference_min_max_location(shape, DataType::S16, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - min_loc.map(); - max_loc.map(); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); - - ref_min_loc.unmap(); - ref_max_loc.unmap(); - min_loc.unmap(); - max_loc.unmap(); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (Small2DShapes() + Large2DShapes()), - shape) -{ - // Create tensor - CLTensor src = create_tensor<CLTensor>(shape, DataType::F32); - - validate_configuration(src, shape); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes(), - shape) -{ - // Create output storage - float min; - float max; - CLCoordinates2DArray min_loc(shape.total_size()); - CLCoordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - float ref_min; - float ref_max; - CLCoordinates2DArray ref_min_loc(shape.total_size()); - CLCoordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, DataType::F32, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - ref_min_loc.map(); - ref_max_loc.map(); - - Reference::compute_reference_min_max_location(shape, DataType::F32, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - min_loc.map(); - max_loc.map(); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); - - ref_min_loc.unmap(); - ref_max_loc.unmap(); - min_loc.unmap(); - max_loc.unmap(); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, Large2DShapes(), - shape) -{ - // Create output storage - float min; - float max; - CLCoordinates2DArray min_loc(shape.total_size()); - CLCoordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - float ref_min; - float ref_max; - CLCoordinates2DArray ref_min_loc(shape.total_size()); - CLCoordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, DataType::F32, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - ref_min_loc.map(); - ref_max_loc.map(); - - Reference::compute_reference_min_max_location(shape, DataType::F32, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - min_loc.map(); - max_loc.map(); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); - - ref_min_loc.unmap(); - ref_max_loc.unmap(); - min_loc.unmap(); - max_loc.unmap(); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/NonLinearFilter.cpp b/tests/validation/CL/NonLinearFilter.cpp deleted file mode 100644 index f453f27e8a..0000000000 --- a/tests/validation/CL/NonLinearFilter.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Helpers.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/functions/CLNonLinearFilter.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::validation; - -namespace -{ -/** Compute NonLinearFilter function. - * - * @param[in] input Shape of the input and output tensors. - * @param[in] function Non linear function to perform - * @param[in] mask_size Mask size. Supported sizes: 3, 5 - * @param[in] pattern Mask pattern - * @param[in] mask The given mask. Will be used only if pattern is specified to PATTERN_OTHER - * @param[in] border_mode Strategy to use for borders. - * @param[in] constant_border_value (Optional) Constant value to use for borders if border_mode is set to CONSTANT. - * - * @return Computed output CL tensor. - */ -CLTensor compute_non_linear_filter(const TensorShape &shape, NonLinearFilterFunction function, unsigned int mask_size, - MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode, - uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - // Create and configure function - CLNonLinearFilter filter; - filter.configure(&src, &dst, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - filter.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(NonLinearFilter) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) - * NonLinearFilterFunctions() * boost::unit_test::data::make({ 3U, 5U }) - * boost::unit_test::data::make({ MatrixPattern::BOX, MatrixPattern::CROSS, MatrixPattern::DISK }) * BorderModes(), - shape, function, mask_size, pattern, border_mode) -{ - std::mt19937 generator(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - const uint8_t constant_border_value = distribution_u8(generator); - - // Create the mask - uint8_t mask[mask_size * mask_size]; - fill_mask_from_pattern(mask, mask_size, mask_size, pattern); - const auto half_mask_size = static_cast<int>(mask_size / 2); - - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLNonLinearFilter filter; - filter.configure(&src, &dst, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, BorderSize(half_mask_size)); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), ((MatrixPattern::OTHER == pattern) ? 1 : 8)); - calculator.set_border_mode(border_mode); - calculator.set_border_size(half_mask_size); - - const PaddingSize write_padding = calculator.required_padding(PaddingCalculator::Option::EXCLUDE_BORDER); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-half_mask_size); - - const PaddingSize read_padding = calculator.required_padding(PaddingCalculator::Option::INCLUDE_BORDER); - - validate(src.info()->padding(), read_padding); - validate(dst.info()->padding(), write_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() - * NonLinearFilterFunctions() * boost::unit_test::data::make({ 3U, 5U }) - * boost::unit_test::data::make({ MatrixPattern::BOX, MatrixPattern::CROSS, MatrixPattern::DISK }) * BorderModes(), - shape, function, mask_size, pattern, border_mode) -{ - std::mt19937 generator(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - const uint8_t constant_border_value = distribution_u8(generator); - - // Create the mask - uint8_t mask[mask_size * mask_size]; - fill_mask_from_pattern(mask, mask_size, mask_size, pattern); - - // Compute function - CLTensor dst = compute_non_linear_filter(shape, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_non_linear_filter(shape, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, BorderSize(static_cast<int>(mask_size / 2))); - - // Validate output - validate(CLAccessor(dst), ref_dst, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() - * NonLinearFilterFunctions() * boost::unit_test::data::make({ 3U, 5U }) - * boost::unit_test::data::make({ MatrixPattern::BOX, MatrixPattern::CROSS, MatrixPattern::DISK }) * BorderModes(), - shape, function, mask_size, pattern, border_mode) -{ - std::mt19937 generator(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - const uint8_t constant_border_value = distribution_u8(generator); - - // Create the mask - uint8_t mask[mask_size * mask_size]; - fill_mask_from_pattern(mask, mask_size, mask_size, pattern); - - // Compute function - CLTensor dst = compute_non_linear_filter(shape, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_non_linear_filter(shape, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, BorderSize(static_cast<int>(mask_size / 2))); - - // Validate output - validate(CLAccessor(dst), ref_dst, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/NormalizationLayer.cpp b/tests/validation/CL/NormalizationLayer.cpp new file mode 100644 index 0000000000..4d14649a91 --- /dev/null +++ b/tests/validation/CL/NormalizationLayer.cpp @@ -0,0 +1,141 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLNormalizationLayer.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/NormalizationTypesDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/NormalizationLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr AbsoluteTolerance<float> tolerance_f16(0.01f); +constexpr AbsoluteTolerance<float> tolerance_f32(0.00001f); +/** Tolerance for fixed point operations */ +constexpr AbsoluteTolerance<int8_t> tolerance_qs8(2); +constexpr AbsoluteTolerance<int16_t> tolerance_qs16(2); + +/** Input data set. */ +const auto NormalizationDataset = combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("NormType", { NormType::IN_MAP_1D, NormType::CROSS_MAP })), + framework::dataset::make("NormalizationSize", 3, 9, 2)), + framework::dataset::make("Beta", { 0.5f, 1.f, 2.f })); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(NormalizationLayer) + +//TODO(COMPMID-415): Missing configuration? + +template <typename T> +using CLNormalizationLayerFixture = NormalizationValidationFixture<CLTensor, CLAccessor, CLNormalizationLayer, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLNormalizationLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(NormalizationDataset, framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLNormalizationLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(NormalizationDataset, framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLNormalizationLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(NormalizationDataset, framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLNormalizationLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(NormalizationDataset, framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using CLNormalizationLayerFixedPointFixture = NormalizationValidationFixedPointFixture<CLTensor, CLAccessor, CLNormalizationLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// Testing for fixed point position [1,6) as reciprocal limits the maximum fixed point position to 5 +FIXTURE_DATA_TEST_CASE(RunSmall, CLNormalizationLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(NormalizationDataset, framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs8); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLNormalizationLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(NormalizationDataset, framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs8); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 5 +FIXTURE_DATA_TEST_CASE(RunSmall, CLNormalizationLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(NormalizationDataset, framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLNormalizationLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(NormalizationDataset, framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs16); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/PixelWiseMultiplication.cpp b/tests/validation/CL/PixelWiseMultiplication.cpp deleted file mode 100644 index 375c77dedf..0000000000 --- a/tests/validation/CL/PixelWiseMultiplication.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 "CL/CLAccessor.h" -#include "TypePrinter.h" -#include "tests/Globals.h" -#include "tests/Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" - -#include "arm_compute/runtime/CL/functions/CLPixelWiseMultiplication.h" - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -const float tolerance_f32 = 1.f; /**< Tolerance value for comparing reference's output against implementation's output for float input */ -const float tolerance_f16 = 1.f; /**< Tolerance value for comparing reference's output against implementation's output for float input */ - -/** Compute CL pixel-wise multiplication function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] scale Non-negative scale. - * @param[in] convert_policy Overflow policy of the operation. - * @param[in] rounding_policy Rounding policy of the operation. - * @param[in] fixed_point_position (Optional) Fixed point position that expresses the number of bits for the fractional part of the number. - * - * @return Computed output tensor. - */ -CLTensor compute_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy, - int fixed_point_position = 0) -{ - // Create tensors - CLTensor src1 = create_tensor<CLTensor>(shape, dt_in0, 1, fixed_point_position); - CLTensor src2 = create_tensor<CLTensor>(shape, dt_in1, 1, fixed_point_position); - CLTensor dst = create_tensor<CLTensor>(shape, dt_out, 1, fixed_point_position); - - // Create and configure function - CLPixelWiseMultiplication multiply; - multiply.configure(&src1, &src2, &dst, scale, convert_policy, rounding_policy); - - // Allocate tensors - src1.allocator()->allocate(); - src2.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src1.info()->is_resizable()); - BOOST_TEST(!src2.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src1), 0); - library->fill_tensor_uniform(CLAccessor(src2), 1); - - // Compute function - multiply.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(PixelWiseMultiplication) - -BOOST_AUTO_TEST_SUITE(Float16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * DataType::F16 *ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP, - shape, dt, convert_policy, rounding_policy) -{ - constexpr float scale = 1.f / 255.f; - - // Compute function - CLTensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy); - - // Validate output - validate(CLAccessor(dst), ref_dst, tolerance_f16); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * DataType::F32 *ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP, - shape, dt, convert_policy, rounding_policy) -{ - constexpr float scale = 1.f / 255.f; - - // Compute function - CLTensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy); - - // Validate output - validate(CLAccessor(dst), ref_dst, tolerance_f32); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Quantized) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * DataType::QS8 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange<int>(1, 7), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * DataType::QS16 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange<int>(1, 15), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - CLTensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif // DOXYGEN_SKIP_THIS diff --git a/tests/validation/CL/PoolingLayer.cpp b/tests/validation/CL/PoolingLayer.cpp new file mode 100644 index 0000000000..24380cb1f0 --- /dev/null +++ b/tests/validation/CL/PoolingLayer.cpp @@ -0,0 +1,142 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLPoolingLayer.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/PoolingTypesDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/PoolingLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Input data set for float data types */ +const auto PoolingLayerDatasetFP = combine(combine(datasets::PoolingTypes(), framework::dataset::make("PoolingSize", { 2, 3, 7 })), + framework::dataset::make("PadStride", { PadStrideInfo(1, 1, 0, 0), PadStrideInfo(2, 1, 0, 0), PadStrideInfo(1, 2, 1, 1), PadStrideInfo(2, 2, 1, 0) })); + +/** Input data set for quantized data types */ +const auto PoolingLayerDatasetQS = combine(combine(datasets::PoolingTypes(), framework::dataset::make("PoolingSize", { 2, 3 })), + framework::dataset::make("PadStride", { PadStrideInfo(1, 1, 0, 0), PadStrideInfo(2, 1, 0, 0), PadStrideInfo(1, 2, 1, 1), PadStrideInfo(2, 2, 1, 0) })); + +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for float types */ +constexpr AbsoluteTolerance<float> tolerance_f16(0.01f); /**< Tolerance value for comparing reference's output against implementation's output for float types */ +constexpr AbsoluteTolerance<float> tolerance_qs8(3); /**< Tolerance value for comparing reference's output against implementation's output for quantized input */ +constexpr AbsoluteTolerance<float> tolerance_qs16(6); /**< Tolerance value for comparing reference's output against implementation's output for quantized input */ +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(PoolingLayer) + +template <typename T> +using CLPoolingLayerFixture = PoolingLayerValidationFixture<CLTensor, CLAccessor, CLPoolingLayer, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLPoolingLayerFixture<float>, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), combine(PoolingLayerDatasetFP, framework::dataset::make("DataType", + DataType::F32)))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLPoolingLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), combine(PoolingLayerDatasetFP, framework::dataset::make("DataType", + DataType::F32)))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() + +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLPoolingLayerFixture<half_float::half>, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), combine(PoolingLayerDatasetFP, + framework::dataset::make("DataType", DataType::F16)))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLPoolingLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), combine(PoolingLayerDatasetFP, + framework::dataset::make("DataType", DataType::F16)))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using CLPoolingLayerFixedPointFixture = PoolingLayerValidationFixedPointFixture<CLTensor, CLAccessor, CLPoolingLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +FIXTURE_DATA_TEST_CASE(RunSmall, CLPoolingLayerFixedPointFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(datasets::SmallShapes(), combine(PoolingLayerDatasetQS, + framework::dataset::make("DataType", DataType::QS8))), + framework::dataset::make("FractionalBits", 1, 4))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs8); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLPoolingLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), combine(PoolingLayerDatasetQS, + framework::dataset::make("DataType", DataType::QS8))), + framework::dataset::make("FractionalBits", 1, 4))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs8); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLPoolingLayerFixedPointFixture<int16_t>, framework::DatasetMode::ALL, combine(combine(datasets::SmallShapes(), combine(PoolingLayerDatasetQS, + framework::dataset::make("DataType", DataType::QS16))), + framework::dataset::make("FractionalBits", 1, 12))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLPoolingLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), combine(PoolingLayerDatasetQS, + framework::dataset::make("DataType", DataType::QS16))), + framework::dataset::make("FractionalBits", 1, 12))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qs16); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/ROIPoolingLayer.cpp b/tests/validation/CL/ROIPoolingLayer.cpp deleted file mode 100644 index 19d7903128..0000000000 --- a/tests/validation/CL/ROIPoolingLayer.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 "CL/CLAccessor.h" -#include "CL/CLArrayAccessor.h" -#include "TypePrinter.h" -#include "arm_compute/runtime/CL/CLArray.h" -#include "arm_compute/runtime/CL/functions/CLROIPoolingLayer.h" -#include "tests/Globals.h" -#include "tests/Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include <random> -#include <vector> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -CLTensor compute_roi_pooling_layer(const TensorShape &shape, DataType dt, const std::vector<ROI> &rois, ROIPoolingLayerInfo pool_info) -{ - TensorShape shape_dst; - shape_dst.set(0, pool_info.pooled_width()); - shape_dst.set(1, pool_info.pooled_height()); - shape_dst.set(2, shape.z()); - shape_dst.set(3, rois.size()); - - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, dt); - CLTensor dst = create_tensor<CLTensor>(shape_dst, dt); - - // Create ROI array - CLArray<ROI> rois_array(rois.size()); - fill_array(CLArrayAccessor<ROI>(rois_array), rois); - - // Create and configure function - CLROIPoolingLayer roi_pool; - roi_pool.configure(&src, &rois_array, &dst, pool_info); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - std::uniform_real_distribution<> distribution(-1, 1); - library->fill(CLAccessor(src), distribution, 0); - - // Compute function - roi_pool.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(ROIPoolingLayer) - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, boost::unit_test::data::make({ DataType::F16, DataType::F32 }) * boost::unit_test::data::make({ 10, 20, 40 }) * boost::unit_test::data::make({ 7, 9 }) * - boost::unit_test::data::make({ 1.f / 8.f, 1.f / 16.f }), - dt, num_rois, roi_pool_size, roi_scale) -{ - TensorShape shape(50U, 47U, 2U, 3U); - ROIPoolingLayerInfo pool_info(roi_pool_size, roi_pool_size, roi_scale); - - // Construct ROI vector - std::vector<ROI> rois = generate_random_rois(shape, pool_info, num_rois, user_config.seed); - - // Compute function - CLTensor dst = compute_roi_pooling_layer(shape, dt, rois, pool_info); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_roi_pooling_layer(shape, dt, rois, pool_info); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/ReductionOperation.cpp b/tests/validation/CL/ReductionOperation.cpp new file mode 100644 index 0000000000..5896add68f --- /dev/null +++ b/tests/validation/CL/ReductionOperation.cpp @@ -0,0 +1,78 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLReductionOperation.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ReductionOperationDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ReductionOperationFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr RelativeTolerance tolerance_f32(0.00001f); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(ReductionOperation) + +template <typename T> +using CLReductionOperationFixture = ReductionOperationValidationFixture<CLTensor, CLAccessor, CLReductionOperation, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLReductionOperationFixture<float>, framework::DatasetMode::PRECOMMIT, + combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("Axis", { 0 })), datasets::ReductionOperations())) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLReductionOperationFixture<float>, framework::DatasetMode::NIGHTLY, + combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("Axis", { 0 })), datasets::ReductionOperations())) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/Scale.cpp b/tests/validation/CL/Scale.cpp new file mode 100644 index 0000000000..d5866fad97 --- /dev/null +++ b/tests/validation/CL/Scale.cpp @@ -0,0 +1,129 @@ +/* + * 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 "arm_compute/core/Helpers.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/functions/CLScale.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/BorderModeDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Helpers.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ScaleFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance */ +constexpr AbsoluteTolerance<uint8_t> tolerance(1); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(Scale) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), + framework::dataset::make("InterpolationPolicy", { InterpolationPolicy::NEAREST_NEIGHBOR, InterpolationPolicy::BILINEAR })), + datasets::BorderModes()), + shape, data_type, policy, border_mode) +{ + std::mt19937 generator(library->seed()); + std::uniform_real_distribution<float> distribution_float(0.25, 2); + const float scale_x = distribution_float(generator); + const float scale_y = distribution_float(generator); + std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); + uint8_t constant_border_value = distribution_u8(generator); + + // Create tensors + CLTensor src = create_tensor<CLTensor>(shape, data_type); + TensorShape shape_scaled(shape); + shape_scaled.set(0, shape[0] * scale_x); + shape_scaled.set(1, shape[1] * scale_y); + CLTensor dst = create_tensor<CLTensor>(shape_scaled, data_type); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLScale clscale; + clscale.configure(&src, &dst, policy, border_mode, constant_border_value); + + // Validate valid region + const ValidRegion dst_valid_region = calculate_valid_region_scale(*(src.info()), shape_scaled, policy, BorderSize(1), (border_mode == BorderMode::UNDEFINED)); + + validate(dst.info()->valid_region(), dst_valid_region); + + // Validate padding + PaddingCalculator calculator(shape_scaled.x(), 4); + calculator.set_border_mode(border_mode); + + const PaddingSize read_padding(1); + const PaddingSize write_padding = calculator.required_padding(PaddingCalculator::Option::EXCLUDE_BORDER); + validate(src.info()->padding(), read_padding); + validate(dst.info()->padding(), write_padding); +} + +template <typename T> +using CLScaleFixture = ScaleValidationFixture<CLTensor, CLAccessor, CLScale, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, CLScaleFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8)), + framework::dataset::make("InterpolationPolicy", +{ InterpolationPolicy::NEAREST_NEIGHBOR, InterpolationPolicy::BILINEAR })), +datasets::BorderModes())) +{ + //Create valid region + TensorInfo src_info(_shape, 1, _data_type); + const ValidRegion valid_region = calculate_valid_region_scale(src_info, _reference.shape(), _policy, BorderSize(1), (_border_mode == BorderMode::UNDEFINED)); + + // Validate output + validate(CLAccessor(_target), _reference, valid_region, tolerance); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLScaleFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8)), + framework::dataset::make("InterpolationPolicy", +{ InterpolationPolicy::NEAREST_NEIGHBOR, InterpolationPolicy::BILINEAR })), +datasets::BorderModes())) +{ + //Create valid region + TensorInfo src_info(_shape, 1, _data_type); + const ValidRegion valid_region = calculate_valid_region_scale(src_info, _reference.shape(), _policy, BorderSize(1), (_border_mode == BorderMode::UNDEFINED)); + + // Validate output + validate(CLAccessor(_target), _reference, valid_region, tolerance); +} +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/Sobel3x3.cpp b/tests/validation/CL/Sobel3x3.cpp deleted file mode 100644 index 9e32a3da66..0000000000 --- a/tests/validation/CL/Sobel3x3.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLSubTensor.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLSobel3x3.h" - -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 3; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute CL Sobel 3x3 function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed output tensor. - */ -std::pair<CLTensor, CLTensor> compute_sobel_3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst_x = create_tensor<CLTensor>(shape, DataType::S16); - CLTensor dst_y = create_tensor<CLTensor>(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - // Create sobel image configure function - CLSobel3x3 sobel_3x3; - sobel_3x3.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst_x.allocator()->allocate(); - dst_y.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst_x.info()->is_resizable()); - BOOST_TEST(!dst_y.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - sobel_3x3.run(); - - return std::make_pair(std::move(dst_x), std::move(dst_y)); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(Sobel3x3) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst_x = create_tensor<CLTensor>(shape, DataType::S16); - CLTensor dst_y = create_tensor<CLTensor>(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst_x.info()->is_resizable()); - BOOST_TEST(dst_y.info()->is_resizable()); - - // Create sobel 3x3 configure function - CLSobel3x3 sobel_3x3; - sobel_3x3.configure(&src, &dst_x, &dst_y, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst_x.info()->valid_region(), dst_valid_region); - validate(dst_y.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - - calculator.set_border_mode(border_mode); - calculator.set_border_size(1); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-1); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst_x.info()->padding(), dst_padding); - validate(dst_y.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair<CLTensor, CLTensor> dst = compute_sobel_3x3(shape, border_mode, constant_border_value); - - // Compute reference - std::pair<RawTensor, RawTensor> ref_dst = Reference::compute_reference_sobel_3x3(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(CLAccessor(dst.first), ref_dst.first, valid_region); - validate(CLAccessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair<CLTensor, CLTensor> dst = compute_sobel_3x3(shape, border_mode, constant_border_value); - - // Compute reference - std::pair<RawTensor, RawTensor> ref_dst = Reference::compute_reference_sobel_3x3(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(CLAccessor(dst.first), ref_dst.first, valid_region); - validate(CLAccessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/Sobel5x5.cpp b/tests/validation/CL/Sobel5x5.cpp deleted file mode 100644 index a7c971aa3a..0000000000 --- a/tests/validation/CL/Sobel5x5.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/CLSubTensor.h" -#include "arm_compute/runtime/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLSobel5x5.h" - -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 5; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute CL Sobel 5x5 function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed output tensor. - */ -std::pair<CLTensor, CLTensor> compute_sobel_5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst_x = create_tensor<CLTensor>(shape, DataType::S16); - CLTensor dst_y = create_tensor<CLTensor>(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - // Create sobel image configure function - CLSobel5x5 sobel_5x5; - sobel_5x5.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst_x.allocator()->allocate(); - dst_y.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst_x.info()->is_resizable()); - BOOST_TEST(!dst_y.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - sobel_5x5.run(); - - return std::make_pair(std::move(dst_x), std::move(dst_y)); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(Sobel5x5) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst_x = create_tensor<CLTensor>(shape, DataType::S16); - CLTensor dst_y = create_tensor<CLTensor>(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst_x.info()->is_resizable()); - BOOST_TEST(dst_y.info()->is_resizable()); - - // Create sobel 5x5 configure function - CLSobel5x5 sobel_5x5; - sobel_5x5.configure(&src, &dst_x, &dst_y, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst_x.info()->valid_region(), dst_valid_region); - validate(dst_y.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - calculator.set_border_mode(border_mode); - calculator.set_border_size(2); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-2); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst_x.info()->padding(), dst_padding); - validate(dst_y.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair<CLTensor, CLTensor> dst = compute_sobel_5x5(shape, border_mode, constant_border_value); - - // Compute reference - std::pair<RawTensor, RawTensor> ref_dst = Reference::compute_reference_sobel_5x5(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(CLAccessor(dst.first), ref_dst.first, valid_region); - validate(CLAccessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair<CLTensor, CLTensor> dst = compute_sobel_5x5(shape, border_mode, constant_border_value); - - // Compute reference - std::pair<RawTensor, RawTensor> ref_dst = Reference::compute_reference_sobel_5x5(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(CLAccessor(dst.first), ref_dst.first, valid_region); - validate(CLAccessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/SoftmaxLayer.cpp b/tests/validation/CL/SoftmaxLayer.cpp new file mode 100644 index 0000000000..c4a9970b78 --- /dev/null +++ b/tests/validation/CL/SoftmaxLayer.cpp @@ -0,0 +1,168 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "arm_compute/runtime/CL/functions/CLSoftmaxLayer.h" +#include "tests/CL/CLAccessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/SoftmaxLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr AbsoluteTolerance<float> tolerance_f16(0.002f); +constexpr AbsoluteTolerance<float> tolerance_f32(0.000001f); +/** Tolerance for fixed point operations */ +constexpr AbsoluteTolerance<int8_t> tolerance_fixed_point(2); + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ + DataType::F16, + DataType::F32, + DataType::QS8, + DataType::QS16, +}); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(SoftmaxLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), CNNDataTypes), shape, data_type) +{ + // Set fixed point position data type allowed + const int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + // Create tensors + CLTensor src = create_tensor<CLTensor>(shape, data_type, 1, fixed_point_position); + CLTensor dst = create_tensor<CLTensor>(shape, data_type, 1, fixed_point_position); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + CLSoftmaxLayer smx_layer; + smx_layer.configure(&src, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using CLSoftmaxLayerFixture = SoftmaxValidationFixture<CLTensor, CLAccessor, CLSoftmaxLayer, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLSoftmaxLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLSoftmaxLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLSoftmaxLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLSoftmaxLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using CLSoftmaxLayerFixedPointFixture = SoftmaxValidationFixedPointFixture<CLTensor, CLAccessor, CLSoftmaxLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// Testing for fixed point position [1,6) as reciprocal limits the maximum fixed point position to 5 +FIXTURE_DATA_TEST_CASE(RunSmall, CLSoftmaxLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fixed_point); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLSoftmaxLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fixed_point); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14 +FIXTURE_DATA_TEST_CASE(RunSmall, CLSoftmaxLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fixed_point); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLSoftmaxLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fixed_point); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/TableLookup.cpp b/tests/validation/CL/TableLookup.cpp deleted file mode 100644 index 40e847f1cd..0000000000 --- a/tests/validation/CL/TableLookup.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "CL/CLLutAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "RawLutAccessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Helpers.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/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLTableLookup.h" - -#include "boost_wrapper.h" - -#include <map> -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -/** Compute Table Lookup function. - * - * @param[in] shape Shape of the input tensors - * @param[in] data_type Type of the input/output tensor - * @param[in] lut The input LUT. - * - * @return Computed output cl tensor. - */ -CLTensor compute_table_lookup(const TensorShape &shape, DataType data_type, CLLut &lut) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, data_type); - CLTensor dst = create_tensor<CLTensor>(shape, data_type); - - // Create and configure function - CLTableLookup table_lookup; - table_lookup.configure(&src, &lut, &dst); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - table_lookup.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(TableLookup) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, data_type) -{ - //Create Lut - const int num_elem = (data_type == DataType::U8) ? std::numeric_limits<uint8_t>::max() + 1 : std::numeric_limits<int16_t>::max() - std::numeric_limits<int16_t>::lowest() + 1; - CLLut cllut(num_elem, data_type); - - if(data_type == DataType::U8) - { - fill_lookuptable(CLLutAccessor<uint8_t>(cllut)); - } - else - { - fill_lookuptable(CLLutAccessor<int16_t>(cllut)); - } - - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, data_type); - CLTensor dst = create_tensor<CLTensor>(shape, data_type); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLTableLookup table_lookup; - table_lookup.configure(&src, &cllut, &dst); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 8).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, - SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, data_type) -{ - //Create Lut - const int num_elem = (data_type == DataType::U8) ? std::numeric_limits<uint8_t>::max() + 1 : std::numeric_limits<int16_t>::max() - std::numeric_limits<int16_t>::lowest() + 1; - CLLut cllut(num_elem, data_type); - - if(data_type == DataType::U8) - { - //Create rawLut - std::map<uint8_t, uint8_t> rawlut; - - //Fill the Lut - fill_lookuptable(CLLutAccessor<uint8_t>(cllut)); - fill_lookuptable(RawLutAccessor<uint8_t>(rawlut)); - - // Compute function - CLTensor dst = compute_table_lookup(shape, data_type, cllut); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_table_lookup(shape, data_type, rawlut); - - // Validate output - validate(CLAccessor(dst), ref_dst); - } - else - { - //Create rawLut - std::map<int16_t, int16_t> rawlut; - - //Fill the Lut - fill_lookuptable(CLLutAccessor<int16_t>(cllut)); - fill_lookuptable(RawLutAccessor<int16_t>(rawlut)); - - // Compute function - CLTensor dst = compute_table_lookup(shape, data_type, cllut); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_table_lookup(shape, data_type, rawlut); - - // Validate output - validate(CLAccessor(dst), ref_dst); - } -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, - LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, data_type) -{ - //Create Lut - const int num_elem = (data_type == DataType::U8) ? std::numeric_limits<uint8_t>::max() + 1 : std::numeric_limits<int16_t>::max() - std::numeric_limits<int16_t>::lowest() + 1; - CLLut cllut(num_elem, data_type); - - if(data_type == DataType::U8) - { - //Create rawLut - std::map<uint8_t, uint8_t> rawlut; - - //Fill the Lut - fill_lookuptable(CLLutAccessor<uint8_t>(cllut)); - fill_lookuptable(RawLutAccessor<uint8_t>(rawlut)); - - // Compute function - CLTensor dst = compute_table_lookup(shape, data_type, cllut); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_table_lookup(shape, data_type, rawlut); - - // Validate output - validate(CLAccessor(dst), ref_dst); - } - else - { - //Create rawLut - std::map<int16_t, int16_t> rawlut; - - //Fill the Lut - fill_lookuptable(CLLutAccessor<int16_t>(cllut)); - fill_lookuptable(RawLutAccessor<int16_t>(rawlut)); - - // Compute function - CLTensor dst = compute_table_lookup(shape, data_type, cllut); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_table_lookup(shape, data_type, rawlut); - - // Validate output - validate(CLAccessor(dst), ref_dst); - } -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/Threshold.cpp b/tests/validation/CL/Threshold.cpp deleted file mode 100644 index a2e7b7b4ba..0000000000 --- a/tests/validation/CL/Threshold.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "dataset/ThresholdDataset.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/CL/CLTensor.h" -#include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLThreshold.h" - -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -/** Compute Threshold function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] threshold Threshold. When the threshold type is RANGE, this is used as the lower threshold. - * @param[in] false_value value to set when the condition is not respected. - * @param[in] true_value value to set when the condition is respected. - * @param[in] type Thresholding type. Either RANGE or BINARY. - * @param[in] upper Upper threshold. Only used when the thresholding type is RANGE. - * - * @return Computed output tensor. - */ -CLTensor compute_threshold(const TensorShape &shape, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - // Create and configure function - CLThreshold thrsh; - thrsh.configure(&src, &dst, threshold, false_value, true_value, type, upper); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - thrsh.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(Threshold) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, - (SmallShapes() + LargeShapes()) * ThresholdDataset(), - shape, threshold_conf) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLThreshold cl_threshold; - cl_threshold.configure(&src, &dst, threshold_conf.threshold, threshold_conf.false_value, threshold_conf.true_value, threshold_conf.type, threshold_conf.upper); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, - SmallShapes() * ThresholdDataset(), - shape, threshold_conf) -{ - // Compute function - CLTensor dst = compute_threshold(shape, threshold_conf.threshold, threshold_conf.false_value, threshold_conf.true_value, threshold_conf.type, threshold_conf.upper); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_threshold(shape, threshold_conf.threshold, threshold_conf.false_value, threshold_conf.true_value, threshold_conf.type, threshold_conf.upper); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, - LargeShapes() * ThresholdDataset(), - shape, threshold_conf) -{ - // Compute function - CLTensor dst = compute_threshold(shape, threshold_conf.threshold, threshold_conf.false_value, threshold_conf.true_value, threshold_conf.type, threshold_conf.upper); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_threshold(shape, threshold_conf.threshold, threshold_conf.false_value, threshold_conf.true_value, threshold_conf.type, threshold_conf.upper); - - // Validate output - validate(CLAccessor(dst), ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CL/WarpPerspective.cpp b/tests/validation/CL/WarpPerspective.cpp deleted file mode 100644 index 260b22be03..0000000000 --- a/tests/validation/CL/WarpPerspective.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "CL/CLAccessor.h" -#include "Globals.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Helpers.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/CL/functions/CLWarpPerspective.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::validation; - -namespace -{ -/** Compute Warp Perspective function. - * - * @param[in] input Shape of the input and output tensors. - * @param[in] matrix The perspective matrix. Must be 3x3 of type float. - * @param[in] policy The interpolation type. - * @param[in] border_mode Strategy to use for borders. - * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT. - * - * @return Computed output tensor. - */ -CLTensor compute_warp_perspective(const TensorShape &shape, const float *matrix, InterpolationPolicy policy, - BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - // Create and configure function - CLWarpPerspective warp_perspective; - warp_perspective.configure(&src, &dst, matrix, policy, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(CLAccessor(src), 0); - - // Compute function - warp_perspective.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(CL) -BOOST_AUTO_TEST_SUITE(WarpPerspective) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) - * boost::unit_test::data::make({ InterpolationPolicy::BILINEAR, InterpolationPolicy::NEAREST_NEIGHBOR }) * BorderModes(), - shape, policy, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - constant_border_value = distribution_u8(gen); - } - - std::array<float, 9> matrix; - fill_warp_matrix<9>(matrix, 3, 3); - - // Create tensors - CLTensor src = create_tensor<CLTensor>(shape, DataType::U8); - CLTensor dst = create_tensor<CLTensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - CLWarpPerspective warp_perspective; - warp_perspective.configure(&src, &dst, matrix.data(), policy, border_mode, constant_border_value); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 4); - calculator.set_border_mode(border_mode); - - const PaddingSize read_padding(1); - const PaddingSize write_padding = calculator.required_padding(PaddingCalculator::Option::EXCLUDE_BORDER); - - validate(src.info()->padding(), read_padding); - validate(dst.info()->padding(), write_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() - * boost::unit_test::data::make({ InterpolationPolicy::BILINEAR, InterpolationPolicy::NEAREST_NEIGHBOR }) - * BorderModes(), - shape, policy, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - constant_border_value = distribution_u8(gen); - } - - // Create the valid mask Tensor - RawTensor valid_mask(shape, DataType::U8); - - // Create the matrix - std::array<float, 9> matrix; - fill_warp_matrix<9>(matrix, 3, 3); - - // Compute function - CLTensor dst = compute_warp_perspective(shape, matrix.data(), policy, border_mode, constant_border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_warp_perspective(shape, valid_mask, matrix.data(), policy, border_mode, constant_border_value); - - // Validate output - validate(CLAccessor(dst), ref_dst, valid_mask, 1, 0.2f); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() - * boost::unit_test::data::make({ InterpolationPolicy::NEAREST_NEIGHBOR, InterpolationPolicy::BILINEAR }) * BorderModes(), - shape, policy, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - constant_border_value = distribution_u8(gen); - } - - // Create the valid mask Tensor - RawTensor valid_mask(shape, DataType::U8); - - // Create the matrix - std::array<float, 9> matrix; - fill_warp_matrix<9>(matrix, 3, 3); - - // Compute function - CLTensor dst = compute_warp_perspective(shape, matrix.data(), policy, border_mode, constant_border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_warp_perspective(shape, valid_mask, matrix.data(), policy, border_mode, constant_border_value); - - // Validate output - validate(CLAccessor(dst), ref_dst, valid_mask, 1, 0.2f); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/CMakeLists.txt b/tests/validation/CMakeLists.txt deleted file mode 100644 index 3d8f56610b..0000000000 --- a/tests/validation/CMakeLists.txt +++ /dev/null @@ -1,96 +0,0 @@ -# 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. -cmake_minimum_required (VERSION 3.1) - -add_library(openvx SHARED IMPORTED) -set_target_properties(openvx PROPERTIES - IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../3rdparty/linux/armv7a/libopenvx.so" -) - -add_library(vxu SHARED IMPORTED) -set_target_properties(vxu PROPERTIES - IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../3rdparty/linux/armv7a/libvxu.so" -) - -add_library(OpenCL SHARED IMPORTED) -set_target_properties(OpenCL PROPERTIES - IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../build/opencl-1.2-stubs/libOpenCL.so" - IMPORTED_NO_SONAME 1 -) - -add_definitions(-DBOOST) - -set(ARM_COMPUTE_TARGETS_TO_VALIDATE "all" CACHE STRING "Semicolon-separated list of targets to include in validation.") - -set(ARM_COMPUTE_ALL_TARGETS - NEON - CL - UNIT - VX -) - -if(ARM_COMPUTE_TARGETS_TO_VALIDATE STREQUAL "all") - set(ARM_COMPUTE_TARGETS_TO_VALIDATE ${ARM_COMPUTE_ALL_TARGETS}) -endif() - -list(REMOVE_DUPLICATES ARM_COMPUTE_TARGETS_TO_VALIDATE) - -foreach(TARGET ${ARM_COMPUTE_TARGETS_TO_VALIDATE}) - list(FIND ARM_COMPUTE_ALL_TARGETS ${TARGET} idx) - - if(${idx} LESS 0) - message(FATAL_ERROR "The target '${TARGET}' does not exist. It should be one of\n${ARM_COMPUTE_ALL_TARGETS}") - else() - add_subdirectory(${TARGET}) - endif() -endforeach() - -set(arm_compute_test_validation_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Datasets.h - ${CMAKE_CURRENT_SOURCE_DIR}/Reference.h - ${CMAKE_CURRENT_SOURCE_DIR}/Reference.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ReferenceCPP.h - ${CMAKE_CURRENT_SOURCE_DIR}/ReferenceCPP.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Validation.h - ${CMAKE_CURRENT_SOURCE_DIR}/Validation.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ValidationProgramOptions.h - ${CMAKE_CURRENT_SOURCE_DIR}/ValidationUserConfiguration.h -) - -add_library(arm_compute_test_validation OBJECT - ${arm_compute_test_validation_SOURCE_FILES} -) - -add_executable(arm_compute_validation - $<TARGET_OBJECTS:arm_compute_test_validation> - ${arm_compute_test_validation_TARGET_OBJECTS} - $<TARGET_OBJECTS:tensor_library> - $<TARGET_OBJECTS:arm_compute_test> -) - -target_link_libraries(arm_compute_validation - boost_unit_test_framework - boost_program_options - arm_compute - ${arm_compute_test_validation_TARGET_LIBRARIES} -) diff --git a/tests/validation/CPP/ActivationLayer.cpp b/tests/validation/CPP/ActivationLayer.cpp new file mode 100644 index 0000000000..fa393be5e1 --- /dev/null +++ b/tests/validation/CPP/ActivationLayer.cpp @@ -0,0 +1,158 @@ +/* + * 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 "ActivationLayer.h" + +#include "tests/validation/FixedPoint.h" +#include "tests/validation/Helpers.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type> +SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info) +{ + // Create reference + SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() }; + + // Compute reference + const T a(info.a()); + const T b(info.b()); + + for(int i = 0; i < src.num_elements(); ++i) + { + T x = src[i]; + + switch(info.activation()) + { + case ActivationLayerInfo::ActivationFunction::ABS: + dst[i] = std::abs(x); + break; + case ActivationLayerInfo::ActivationFunction::LINEAR: + dst[i] = a * x + b; + break; + case ActivationLayerInfo::ActivationFunction::LOGISTIC: + dst[i] = static_cast<T>(1) / (static_cast<T>(1) + std::exp(-x)); + break; + case ActivationLayerInfo::ActivationFunction::RELU: + dst[i] = std::max<T>(static_cast<T>(0), x); + break; + case ActivationLayerInfo::ActivationFunction::BOUNDED_RELU: + dst[i] = std::min<T>(a, std::max(static_cast<T>(0), x)); + break; + case ActivationLayerInfo::ActivationFunction::LEAKY_RELU: + dst[i] = (x > 0) ? x : a * x; + break; + case ActivationLayerInfo::ActivationFunction::SOFT_RELU: + dst[i] = std::log(static_cast<T>(1) + std::exp(x)); + break; + case ActivationLayerInfo::ActivationFunction::SQRT: + dst[i] = std::sqrt(x); + break; + case ActivationLayerInfo::ActivationFunction::SQUARE: + dst[i] = x * x; + break; + case ActivationLayerInfo::ActivationFunction::TANH: + dst[i] = a * std::tanh(b * x); + break; + default: + ARM_COMPUTE_ERROR("Unsupported activation function"); + } + } + + return dst; +} + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type> +SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info) +{ + using namespace fixed_point_arithmetic; + + // Create reference + SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() }; + + // Compute reference + const int fixed_point_position = src.fixed_point_position(); + const fixed_point<T> a(info.a(), fixed_point_position); + const fixed_point<T> b(info.b(), fixed_point_position); + const fixed_point<T> const_0(0, fixed_point_position); + const fixed_point<T> const_1(1, fixed_point_position); + + for(int i = 0; i < src.num_elements(); ++i) + { + fixed_point<T> x(src[i], fixed_point_position, true); + + switch(info.activation()) + { + case ActivationLayerInfo::ActivationFunction::ABS: + dst[i] = abs(x).raw(); + break; + case ActivationLayerInfo::ActivationFunction::LINEAR: + dst[i] = add(b, mul(a, x)).raw(); + break; + case ActivationLayerInfo::ActivationFunction::LOGISTIC: + dst[i] = (const_1 / (const_1 + exp(-x))).raw(); + break; + case ActivationLayerInfo::ActivationFunction::RELU: + dst[i] = max(const_0, x).raw(); + break; + case ActivationLayerInfo::ActivationFunction::BOUNDED_RELU: + dst[i] = min(a, max(const_0, x)).raw(); + break; + case ActivationLayerInfo::ActivationFunction::LEAKY_RELU: + dst[i] = (x > const_0) ? x.raw() : mul(a, x).raw(); + break; + case ActivationLayerInfo::ActivationFunction::SOFT_RELU: + dst[i] = log(const_1 + exp(x)).raw(); + break; + case ActivationLayerInfo::ActivationFunction::SQRT: + dst[i] = (const_1 / inv_sqrt(x)).raw(); + break; + case ActivationLayerInfo::ActivationFunction::SQUARE: + dst[i] = mul(x, x).raw(); + break; + case ActivationLayerInfo::ActivationFunction::TANH: + dst[i] = mul(a, tanh(mul(b, x))).raw(); + break; + default: + ARM_COMPUTE_ERROR("Unsupported activation function"); + } + } + + return dst; +} + +template SimpleTensor<float> activation_layer(const SimpleTensor<float> &src, ActivationLayerInfo info); +template SimpleTensor<half_float::half> activation_layer(const SimpleTensor<half_float::half> &src, ActivationLayerInfo info); +template SimpleTensor<qint8_t> activation_layer(const SimpleTensor<qint8_t> &src, ActivationLayerInfo info); +template SimpleTensor<qint16_t> activation_layer(const SimpleTensor<qint16_t> &src, ActivationLayerInfo info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/ActivationLayer.h b/tests/validation/CPP/ActivationLayer.h new file mode 100644 index 0000000000..09f602ffa1 --- /dev/null +++ b/tests/validation/CPP/ActivationLayer.h @@ -0,0 +1,47 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__ +#define __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info); + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__ */ diff --git a/tests/validation/CPP/BitwiseAnd.cpp b/tests/validation/CPP/BitwiseAnd.cpp new file mode 100644 index 0000000000..6fc46b402b --- /dev/null +++ b/tests/validation/CPP/BitwiseAnd.cpp @@ -0,0 +1,51 @@ +/* + * 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 "BitwiseAnd.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> bitwise_and(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2) +{ + SimpleTensor<T> dst(src1.shape(), src1.data_type()); + + for(int i = 0; i < src1.num_elements(); ++i) + { + dst[i] = src1[i] & src2[i]; + } + + return dst; +} + +template SimpleTensor<uint8_t> bitwise_and(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/ValidationProgramOptions.h b/tests/validation/CPP/BitwiseAnd.h index 6b29b807de..eba2fd695f 100644 --- a/tests/validation/ValidationProgramOptions.h +++ b/tests/validation/CPP/BitwiseAnd.h @@ -21,10 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef __ARM_COMPUTE_TEST_VALIDATION_PROGRAM_OPTIONS_H__ -#define __ARM_COMPUTE_TEST_VALIDATION_PROGRAM_OPTIONS_H__ +#ifndef __ARM_COMPUTE_TEST_BITWISE_AND_H__ +#define __ARM_COMPUTE_TEST_BITWISE_AND_H__ -#include "ProgramOptions.h" +#include "tests/SimpleTensor.h" namespace arm_compute { @@ -32,14 +32,12 @@ namespace test { namespace validation { -/** Subclass of @ref ProgramOptions that adds validation specific options. */ -class ValidationProgramOptions : public ProgramOptions +namespace reference { -public: - /** Defines additonal options. */ - ValidationProgramOptions(); -}; +template <typename T> +SimpleTensor<T> bitwise_and(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2); +} // namespace reference } // namespace validation } // namespace test } // namespace arm_compute -#endif /* __ARM_COMPUTE_TEST_VALIDATION_PROGRAM_OPTIONS_H__ */ +#endif /* __ARM_COMPUTE_TEST_BITWISE_AND_H__ */ diff --git a/tests/validation/ValidationUserConfiguration.h b/tests/validation/CPP/BitwiseNot.cpp index a9b8b4fe40..5a6a13b56c 100644 --- a/tests/validation/ValidationUserConfiguration.h +++ b/tests/validation/CPP/BitwiseNot.cpp @@ -21,10 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef __ARM_COMPUTE_TEST_REFERENCE_VALIDATION_USER_CONFIGURATION_H__ -#define __ARM_COMPUTE_TEST_REFERENCE_VALIDATION_USER_CONFIGURATION_H__ - -#include "UserConfiguration.h" +#include "BitwiseNot.h" namespace arm_compute { @@ -32,11 +29,23 @@ namespace test { namespace validation { -// Validation requires no specific configuration -using ValidationUserConfiguration = UserConfiguration; -} // namespace validation +namespace reference +{ +template <typename T> +SimpleTensor<T> bitwise_not(const SimpleTensor<T> &src) +{ + SimpleTensor<T> dst(src.shape(), src.data_type()); -extern validation::ValidationUserConfiguration user_config; + for(int i = 0; i < src.num_elements(); ++i) + { + dst[i] = ~src[i]; + } + + return dst; +} + +template SimpleTensor<uint8_t> bitwise_not(const SimpleTensor<uint8_t> &src); +} // namespace reference +} // namespace validation } // namespace test } // namespace arm_compute -#endif /* __ARM_COMPUTE_TEST_REFERENCE_VALIDATION_USER_CONFIGURATION_H__ */ diff --git a/tests/validation/CL/CLFixture.h b/tests/validation/CPP/BitwiseNot.h index 77538be8f4..b4206f9388 100644 --- a/tests/validation/CL/CLFixture.h +++ b/tests/validation/CPP/BitwiseNot.h @@ -21,10 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef __ARM_COMPUTE_TEST_VALIDATION_CL_CLFIXTURE_H__ -#define __ARM_COMPUTE_TEST_VALIDATION_CL_CLFIXTURE_H__ +#ifndef __ARM_COMPUTE_TEST_BITWISE_NOT_H__ +#define __ARM_COMPUTE_TEST_BITWISE_NOT_H__ -#include "arm_compute/runtime/CL/CLScheduler.h" +#include "tests/SimpleTensor.h" namespace arm_compute { @@ -32,14 +32,12 @@ namespace test { namespace validation { -struct CLFixture +namespace reference { - CLFixture() - { - CLScheduler::get().default_init(); - } -}; +template <typename T> +SimpleTensor<T> bitwise_not(const SimpleTensor<T> &src); +} // namespace reference } // namespace validation } // namespace test } // namespace arm_compute -#endif /* __ARM_COMPUTE_TEST_VALIDATION_CL_CLFIXTURE_H__ */ +#endif /* __ARM_COMPUTE_TEST_BITWISE_NOT_H__ */ diff --git a/tests/validation/CPP/BitwiseOr.cpp b/tests/validation/CPP/BitwiseOr.cpp new file mode 100644 index 0000000000..fc258d54f1 --- /dev/null +++ b/tests/validation/CPP/BitwiseOr.cpp @@ -0,0 +1,51 @@ +/* + * 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 "BitwiseOr.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> bitwise_or(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2) +{ + SimpleTensor<T> dst(src1.shape(), src1.data_type()); + + for(int i = 0; i < src1.num_elements(); ++i) + { + dst[i] = src1[i] | src2[i]; + } + + return dst; +} + +template SimpleTensor<uint8_t> bitwise_or(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/BitwiseOr.h b/tests/validation/CPP/BitwiseOr.h new file mode 100644 index 0000000000..39158cb411 --- /dev/null +++ b/tests/validation/CPP/BitwiseOr.h @@ -0,0 +1,43 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_BITWISE_OR_H__ +#define __ARM_COMPUTE_TEST_BITWISE_OR_H__ + +#include "tests/SimpleTensor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> bitwise_or(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_BITWISE_OR_H__ */ diff --git a/tests/validation/CPP/BitwiseXor.cpp b/tests/validation/CPP/BitwiseXor.cpp new file mode 100644 index 0000000000..b8d275d8b5 --- /dev/null +++ b/tests/validation/CPP/BitwiseXor.cpp @@ -0,0 +1,51 @@ +/* + * 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 "BitwiseXor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> bitwise_xor(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2) +{ + SimpleTensor<T> dst(src1.shape(), src1.data_type()); + + for(int i = 0; i < src1.num_elements(); ++i) + { + dst[i] = src1[i] ^ src2[i]; + } + + return dst; +} + +template SimpleTensor<uint8_t> bitwise_xor(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/BitwiseXor.h b/tests/validation/CPP/BitwiseXor.h new file mode 100644 index 0000000000..3e7721e843 --- /dev/null +++ b/tests/validation/CPP/BitwiseXor.h @@ -0,0 +1,43 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_BITWISE_XOR_H__ +#define __ARM_COMPUTE_TEST_BITWISE_XOR_H__ + +#include "tests/SimpleTensor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> bitwise_xor(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_BITWISE_XOR_H__ */ diff --git a/tests/validation/CPP/ConvolutionLayer.cpp b/tests/validation/CPP/ConvolutionLayer.cpp new file mode 100644 index 0000000000..1824ada791 --- /dev/null +++ b/tests/validation/CPP/ConvolutionLayer.cpp @@ -0,0 +1,205 @@ +/* + * 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 "ConvolutionLayer.h" + +#include "tests/validation/FixedPoint.h" +#include "tests/validation/Helpers.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +namespace +{ +inline bool is_valid_pixel(int i, int min, int max) +{ + return (i >= min && i < max); +} + +// 3D convolution for floating point type +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +void convolution3d(const T *in, const T *weights, const T *bias, T *out, int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights, int fixed_point_position) +{ + ARM_COMPUTE_UNUSED(fixed_point_position); + + const int half_width_weights = width_weights / 2; + const int half_height_weights = height_weights / 2; + + // Reset accumulator + T acc(0); + + // Compute a 2D convolution for each IFM and accumulate the result + for(int ifm = 0; ifm < depth_in; ++ifm) + { + // Compute the offset for the input slice + const int offset_slice_in = xi + yi * width_in + ifm * width_in * height_in; + + // Compute 2D convolution + for(int yk = -half_height_weights; yk <= half_height_weights; ++yk) + { + for(int xk = -half_width_weights; xk <= half_width_weights; ++xk) + { + // Check if the pixel is out-of-bound + if(is_valid_pixel(xi + xk, 0, width_in) && is_valid_pixel(yi + yk, 0, height_in)) + { + const int idx = xk + half_width_weights; + const int idy = yk + half_height_weights; + + const T i_value = in[offset_slice_in + xk + yk * width_in]; + const T w_value = weights[idx + idy * width_weights + ifm * width_weights * height_weights]; + + acc += i_value * w_value; + } + } + } + } + + // Accumulate the bias and store the result + *out = acc + (*bias); +} + +// 3D convolution for fixed point type +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +void convolution3d(const T *in, const T *weights, const T *bias, T *out, int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights, + int fixed_point_position) +{ + const int half_width_weights = width_weights / 2; + const int half_height_weights = height_weights / 2; + + using namespace fixed_point_arithmetic; + using promoted_type = fixed_point_arithmetic::traits::promote_t<T>; + + // Reset accumulator + fixed_point<promoted_type> acc(0, fixed_point_position); + + // Compute a 2D convolution for each IFM and accumulate the result + for(int ifm = 0; ifm < depth_in; ++ifm) + { + // Compute the offset for the input slice + const int offset_slice_in = xi + yi * width_in + ifm * width_in * height_in; + + // Compute 2D convolution + for(int yk = -half_height_weights; yk <= half_height_weights; ++yk) + { + for(int xk = -half_width_weights; xk <= half_width_weights; ++xk) + { + // Check if the pixel is out-of-bound + if(is_valid_pixel(xi + xk, 0, width_in) && is_valid_pixel(yi + yk, 0, height_in)) + { + const int idx = xk + half_width_weights; + const int idy = yk + half_height_weights; + + const fixed_point<promoted_type> i_value(in[offset_slice_in + xk + yk * width_in], fixed_point_position, true); + const fixed_point<promoted_type> w_value(weights[idx + idy * width_weights + ifm * width_weights * height_weights], fixed_point_position, true); + const fixed_point<promoted_type> iw = i_value * w_value; + acc = iw + acc; + } + } + } + } + + // Get the bias + const fixed_point<promoted_type> b(*bias, fixed_point_position, true); + + // Accumulate the bias and covert back + acc = acc + b; + fixed_point<T> res(acc); + *out = res.raw(); +} +} // namespace + +template <typename T> +SimpleTensor<T> convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<T> &bias, const TensorShape &output_shape, const PadStrideInfo &info) +{ + // Create reference + SimpleTensor<T> dst{ output_shape, src.data_type(), 1, src.fixed_point_position() }; + + // Compute reference + const int width_in = src.shape().x(); + const int height_in = src.shape().y(); + const int depth_in = src.shape().z(); + const int width_out = dst.shape().x(); + const int height_out = dst.shape().y(); + const int depth_out = dst.shape().z(); + const int width_weights = weights.shape().x(); + const int height_weights = weights.shape().y(); + const int depth_weights = weights.shape().z(); + const int pad_xi = std::min(static_cast<int>(info.pad().first), width_weights / 2); + const int pad_yi = std::min(static_cast<int>(info.pad().second), height_weights / 2); + const int start_xi = width_weights / 2 - pad_xi; + const int start_yi = height_weights / 2 - pad_yi; + const int end_xi = width_in - start_xi; + const int end_yi = height_in - start_yi; + const int stride_xi = info.stride().first; + const int stride_yi = info.stride().second; + const int num_batches = src.shape().total_size() / (width_in * height_in * depth_in); + + for(int r = 0; r < num_batches; ++r) + { + for(int yi = start_yi; yi < end_yi; yi += stride_yi) + { + for(int xi = start_xi; xi < end_xi; xi += stride_xi) + { + for(int ofm = 0; ofm < depth_out; ++ofm) + { + // 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; + + // Compute 3D convolution + convolution3d(src.data() + offset_in, + weights.data() + ofm * width_weights * height_weights * depth_weights, + bias.data() + ofm, + dst.data() + offset_out, + xi, yi, + width_in, height_in, depth_in, + width_weights, height_weights, + src.fixed_point_position()); + } + } + } + } + + return dst; +} + +template SimpleTensor<float> convolution_layer(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &bias, const TensorShape &output_shape, + const PadStrideInfo &info); +template SimpleTensor<half_float::half> convolution_layer(const SimpleTensor<half_float::half> &src, const SimpleTensor<half_float::half> &weights, const SimpleTensor<half_float::half> &bias, + const TensorShape &output_shape, const PadStrideInfo &info); +template SimpleTensor<qint8_t> convolution_layer(const SimpleTensor<qint8_t> &src, const SimpleTensor<qint8_t> &weights, const SimpleTensor<qint8_t> &bias, const TensorShape &output_shape, + const PadStrideInfo &info); +template SimpleTensor<qint16_t> convolution_layer(const SimpleTensor<qint16_t> &src, const SimpleTensor<qint16_t> &weights, const SimpleTensor<qint16_t> &bias, const TensorShape &output_shape, + const PadStrideInfo &info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/ConvolutionLayer.h b/tests/validation/CPP/ConvolutionLayer.h new file mode 100644 index 0000000000..117e846b1c --- /dev/null +++ b/tests/validation/CPP/ConvolutionLayer.h @@ -0,0 +1,44 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_CONVOLUTION_LAYER_H__ +#define __ARM_COMPUTE_TEST_CONVOLUTION_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<T> &bias, const TensorShape &output_shape, const PadStrideInfo &info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_CONVOLUTION_LAYER_H__ */ diff --git a/tests/validation/CPP/DepthConcatenateLayer.cpp b/tests/validation/CPP/DepthConcatenateLayer.cpp new file mode 100644 index 0000000000..139d26f2b6 --- /dev/null +++ b/tests/validation/CPP/DepthConcatenateLayer.cpp @@ -0,0 +1,104 @@ +/* + * 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 "DepthConcatenateLayer.h" + +#include "tests/validation/FixedPoint.h" +#include "tests/validation/Helpers.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> depthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs) +{ + // Create reference + std::vector<TensorShape> shapes; + + for(const auto &src : srcs) + { + shapes.emplace_back(src.shape()); + } + + DataType dst_type = srcs.empty() ? DataType::UNKNOWN : srcs[0].data_type(); + TensorShape dst_shape = calculate_depth_concatenate_shape(shapes); + SimpleTensor<T> dst(dst_shape, dst_type); + + // Compute reference + int depth_offset = 0; + const int width_out = dst.shape().x(); + const int height_out = dst.shape().y(); + const int depth_out = dst.shape().z(); + const int out_stride_z = width_out * height_out; + const int batches = dst.shape().total_size_upper(3); + + // Set output tensor to 0 + std::fill_n(dst.data(), dst.num_elements(), 0); + + for(const auto &src : srcs) + { + ARM_COMPUTE_ERROR_ON(depth_offset >= depth_out); + ARM_COMPUTE_ERROR_ON(batches != static_cast<int>(src.shape().total_size_upper(3))); + + const int width = src.shape().x(); + const int height = src.shape().y(); + const int depth = src.shape().z(); + const int x_diff = (width_out - width) / 2; + const int y_diff = (height_out - height) / 2; + + const T *src_ptr = src.data(); + + for(int b = 0; b < batches; ++b) + { + const size_t offset_to_first_element = b * out_stride_z * depth_out + depth_offset * out_stride_z + y_diff * width_out + x_diff; + + for(int d = 0; d < depth; ++d) + { + for(int r = 0; r < height; ++r) + { + std::copy(src_ptr, src_ptr + width, dst.data() + offset_to_first_element + d * out_stride_z + r * width_out); + src_ptr += width; + } + } + } + + depth_offset += depth; + } + + return dst; +} + +template SimpleTensor<float> depthconcatenate_layer(const std::vector<SimpleTensor<float>> &srcs); +template SimpleTensor<half_float::half> depthconcatenate_layer(const std::vector<SimpleTensor<half_float::half>> &srcs); +template SimpleTensor<qint8_t> depthconcatenate_layer(const std::vector<SimpleTensor<qint8_t>> &srcs); +template SimpleTensor<qint16_t> depthconcatenate_layer(const std::vector<SimpleTensor<qint16_t>> &srcs); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/DepthConcatenateLayer.h b/tests/validation/CPP/DepthConcatenateLayer.h new file mode 100644 index 0000000000..3c486a8015 --- /dev/null +++ b/tests/validation/CPP/DepthConcatenateLayer.h @@ -0,0 +1,45 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_H__ +#define __ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_H__ + +#include "tests/SimpleTensor.h" + +#include <vector> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> depthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_H__ */ diff --git a/tests/validation/CPP/DepthwiseConvolution.cpp b/tests/validation/CPP/DepthwiseConvolution.cpp new file mode 100644 index 0000000000..ebca333715 --- /dev/null +++ b/tests/validation/CPP/DepthwiseConvolution.cpp @@ -0,0 +1,103 @@ +/* + * 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 "DepthwiseConvolution.h" + +#include "ConvolutionLayer.h" +#include "Utils.h" + +#include "tests/validation/Helpers.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +/** Perform a depthwise convolution + * + * - Three dimensions tensors + * - Third dimention is number of channels + * - Depths of input tensor and filter are equals + * - Padding, stride and output shape "match" + * + */ +template <typename T> +SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const TensorShape &dst_shape, const PadStrideInfo &conv_info) +{ + // Create reference + SimpleTensor<T> dst{ dst_shape, src.data_type(), 1, src.fixed_point_position() }; + + // Compute reference + const size_t filter_width = weights.shape().x(); + const size_t filter_height = weights.shape().y(); + const size_t filter_plane = filter_width * filter_height; + const size_t input_width = src.shape().x(); + const size_t input_height = src.shape().y(); + const size_t input_depth = src.shape().z(); + + const size_t filter_half_size = filter_width / 2; + const size_t pad_x = std::min(filter_half_size, static_cast<size_t>(conv_info.pad().first)); + const size_t pad_y = std::min(filter_half_size, static_cast<size_t>(conv_info.pad().second)); + const size_t minimum_x = -pad_x + filter_half_size; + const size_t minimum_y = -pad_y + filter_half_size; + + int out_pos = 0; + for(size_t z = 0; z < input_depth; ++z) + { + for(size_t y = minimum_y; y < input_height + pad_y - filter_half_size; y += conv_info.stride().second) + { + for(size_t x = minimum_x; x < input_width + pad_x - filter_half_size; x += conv_info.stride().first) + { + Coordinates coords(static_cast<int>(x), static_cast<int>(y), static_cast<int>(z)); + size_t filter_offset = filter_plane * z; + + T val = 0; + for(int j = y - filter_half_size; j <= static_cast<int>(y + filter_half_size); ++j) + { + for(int i = x - filter_half_size; i <= static_cast<int>(x + filter_half_size); ++i) + { + coords.set(0, i); + coords.set(1, j); + val += *(weights.data() + filter_offset) * tensor_elem_at(src, coords, BorderMode::CONSTANT, 0.f); + ++filter_offset; + } + } + coords.set(0, x); + coords.set(1, y); + dst[out_pos++] = saturate_cast<T>(val); + } + } + } + + return dst; +} + +template SimpleTensor<float> depthwise_convolution(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const TensorShape &dst_shape, const PadStrideInfo &conv_info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/DepthwiseConvolution.h b/tests/validation/CPP/DepthwiseConvolution.h new file mode 100644 index 0000000000..6be80fc07f --- /dev/null +++ b/tests/validation/CPP/DepthwiseConvolution.h @@ -0,0 +1,44 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_H__ +#define __ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const TensorShape &dst_shape, const PadStrideInfo &conv_info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_H__ */ diff --git a/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.cpp b/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.cpp new file mode 100644 index 0000000000..7020a854cf --- /dev/null +++ b/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.cpp @@ -0,0 +1,60 @@ +/* + * 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 "DepthwiseConvolution.h" + +#include "DepthwiseSeparableConvolutionLayer.h" + +#include "ConvolutionLayer.h" +#include "Utils.h" + +#include "tests/validation/Helpers.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +// Depthwise separable convolution layer +template <typename T> +SimpleTensor<T> depthwise_separable_convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &depthwise_weights, const TensorShape &depthwise_out_shape, + const SimpleTensor<T> &pointwise_weights, + const SimpleTensor<T> &biases, const TensorShape &dst_shape, const PadStrideInfo &depthwise_conv_info, const PadStrideInfo &pointwise_conv_info) +{ + // Compute reference + SimpleTensor<T> depthwise_out = depthwise_convolution(src, depthwise_weights, depthwise_out_shape, depthwise_conv_info); + SimpleTensor<T> dst = convolution_layer(depthwise_out, pointwise_weights, biases, dst_shape, pointwise_conv_info); + + return dst; +} + +template SimpleTensor<float> depthwise_separable_convolution_layer(const SimpleTensor<float> &in, const SimpleTensor<float> &depthwise_weights, const TensorShape &depthwise_out_shape, + const SimpleTensor<float> &pointwise_weights, const SimpleTensor<float> &biases, const TensorShape &dst_shape, const PadStrideInfo &depthwise_conv_info, const PadStrideInfo &pointwise_conv_info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.h b/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.h new file mode 100644 index 0000000000..71cd013424 --- /dev/null +++ b/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.h @@ -0,0 +1,46 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_H__ +#define __ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> depthwise_separable_convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &depthwise_weights, const TensorShape &depthwise_out_shape, + const SimpleTensor<T> &pointwise_weights, + const SimpleTensor<T> &biases, const TensorShape &dst_shape, const PadStrideInfo &depthwise_conv_info, const PadStrideInfo &pointwise_conv_info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_H__ */ diff --git a/tests/validation/ValidationProgramOptions.cpp b/tests/validation/CPP/DequantizationLayer.cpp index adb8c5ab6c..1c7ec25255 100644 --- a/tests/validation/ValidationProgramOptions.cpp +++ b/tests/validation/CPP/DequantizationLayer.cpp @@ -21,16 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "ValidationProgramOptions.h" - -#include <thread> - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Weffc++" -#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" -#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" -#include "boost/program_options.hpp" -#pragma GCC diagnostic pop +#include "DequantizationLayer.h" namespace arm_compute { @@ -38,13 +29,27 @@ namespace test { namespace validation { -ValidationProgramOptions::ValidationProgramOptions() +namespace reference { - boost::program_options::options_description options("Validation options"); - options.add_options()("runs", boost::program_options::value<unsigned int>()->default_value(1), "Repetitions per test"); - options.add_options()("threads", boost::program_options::value<unsigned int>()->default_value(std::thread::hardware_concurrency()), "Number of parallel CPU threads"); - add_options(options); +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type> +SimpleTensor<float> dequantization_layer(const SimpleTensor<T> &src, float min, float max) +{ + // Create reference + SimpleTensor<float> dst{ src.shape(), DataType::F32 }; + + const float range = max - min; + const float scaling = range / 255.0f; + + for(int i = 0; i < src.num_elements(); ++i) + { + dst[i] = (static_cast<float>(src[i]) * scaling) + min; + } + + return dst; } + +template SimpleTensor<float> dequantization_layer(const SimpleTensor<uint8_t> &src, float min, float max); +} // namespace reference } // namespace validation } // namespace test } // namespace arm_compute diff --git a/tests/validation/CPP/DequantizationLayer.h b/tests/validation/CPP/DequantizationLayer.h new file mode 100644 index 0000000000..3aae338116 --- /dev/null +++ b/tests/validation/CPP/DequantizationLayer.h @@ -0,0 +1,44 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_H__ +#define __ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +SimpleTensor<float> dequantization_layer(const SimpleTensor<T> &src, float min, float max); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_H__ */ diff --git a/tests/validation/CPP/Floor.cpp b/tests/validation/CPP/Floor.cpp new file mode 100644 index 0000000000..1c739448b7 --- /dev/null +++ b/tests/validation/CPP/Floor.cpp @@ -0,0 +1,57 @@ +/* + * 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 "Floor.h" + +#include "tests/validation/Helpers.h" + +#include <cmath> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> floor_layer(const SimpleTensor<T> &src) +{ + // Create reference + SimpleTensor<T> dst{ src.shape(), src.data_type() }; + + // Compute reference + for(int i = 0; i < src.num_elements(); ++i) + { + dst[i] = std::floor(src[i]); + } + + return dst; +} + +template SimpleTensor<float> floor_layer(const SimpleTensor<float> &src); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CL/CLFixture.cpp b/tests/validation/CPP/Floor.h index 38e52c31f6..d95ee303fc 100644 --- a/tests/validation/CL/CLFixture.cpp +++ b/tests/validation/CPP/Floor.h @@ -21,12 +21,24 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "validation/CL/CLFixture.h" +#ifndef __ARM_COMPUTE_TEST_FLOOR_H__ +#define __ARM_COMPUTE_TEST_FLOOR_H__ -#include "boost_wrapper.h" +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -BOOST_GLOBAL_FIXTURE(CLFixture); +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> floor_layer(const SimpleTensor<T> &src); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_FLOOR_H__ */ diff --git a/tests/validation/CPP/FullyConnectedLayer.cpp b/tests/validation/CPP/FullyConnectedLayer.cpp new file mode 100644 index 0000000000..a146535bd9 --- /dev/null +++ b/tests/validation/CPP/FullyConnectedLayer.cpp @@ -0,0 +1,133 @@ +/* + * 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 "FullyConnectedLayer.h" + +#include "tests/validation/FixedPoint.h" +#include "tests/validation/half.h" + +#include <numeric> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +namespace +{ +// Vector matrix multiply for floating point +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +void vector_matrix_multiply(const T *src, const T *weights, const T *bias, T *dst, int cols_weights, int rows_weights, uint8_t fixed_point_position) +{ + ARM_COMPUTE_UNUSED(fixed_point_position); + + for(int y = 0; y < rows_weights; ++y) + { + dst[y] = std::inner_product(src, src + cols_weights, weights, static_cast<T>(0)) + bias[y]; + weights += cols_weights; + } +} + +// Vector matrix multiply for fixed point type +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +void vector_matrix_multiply(const T *src, const T *weights, const T *bias, T *dst, int cols_weights, int rows_weights, uint8_t fixed_point_position) +{ + using namespace fixed_point_arithmetic; + using promoted_type = fixed_point_arithmetic::traits::promote_t<T>; + + for(int y = 0; y < rows_weights; ++y) + { + // Reset accumulator + fixed_point<promoted_type> acc(0, fixed_point_position); + + for(int x = 0; x < cols_weights; ++x) + { + const fixed_point<promoted_type> i_value(src[x], fixed_point_position, true); + const fixed_point<promoted_type> w_value(weights[x], fixed_point_position, true); + acc = acc + i_value * w_value; + } + + // Get the bias + const fixed_point<T> b(bias[y], fixed_point_position, true); + + // Convert back and accumulate the bias + fixed_point<T> res(acc); + res = res + b; + + // Store the result + dst[y] = res.raw(); + + weights += cols_weights; + } +} +} // namespace + +template <typename T> +SimpleTensor<T> fully_connected_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<T> &bias, const TensorShape &dst_shape) +{ + // Create reference + SimpleTensor<T> dst{ TensorShape{ dst_shape }, src.data_type(), 1, src.fixed_point_position() }; + + // Sanity checks + const int num_batch_dimensions = std::max(0, static_cast<int>(dst_shape.num_dimensions()) - 1); + const int num_input_dimensions = src.shape().num_dimensions() - num_batch_dimensions; + const unsigned int linear_input_size = src.shape().total_size_lower(num_input_dimensions); + + ARM_COMPUTE_UNUSED(num_batch_dimensions); + ARM_COMPUTE_UNUSED(num_input_dimensions); + ARM_COMPUTE_UNUSED(linear_input_size); + ARM_COMPUTE_ERROR_ON(weights.shape().x() != linear_input_size); + ARM_COMPUTE_ERROR_ON(weights.shape().y() != bias.shape().x()); + ARM_COMPUTE_ERROR_ON(weights.shape().y() != dst.shape().x()); + + // Compute reference + const int cols_weights = weights.shape().x(); + const int rows_weights = weights.shape().y(); + const int num_batches = dst_shape.total_size_upper(1); + + for(int k = 0; k < num_batches; ++k) + { + vector_matrix_multiply<T>(src.data() + k * cols_weights, + weights.data(), + bias.data(), + dst.data() + k * rows_weights, + cols_weights, + rows_weights, + src.fixed_point_position()); + } + + return dst; +} + +template SimpleTensor<float> fully_connected_layer(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &bias, const TensorShape &dst_shape); +template SimpleTensor<half_float::half> fully_connected_layer(const SimpleTensor<half_float::half> &src, const SimpleTensor<half_float::half> &weights, const SimpleTensor<half_float::half> &bias, + const TensorShape &dst_shape); +template SimpleTensor<qint8_t> fully_connected_layer(const SimpleTensor<qint8_t> &src, const SimpleTensor<qint8_t> &weights, const SimpleTensor<qint8_t> &bias, const TensorShape &dst_shape); +template SimpleTensor<qint16_t> fully_connected_layer(const SimpleTensor<qint16_t> &src, const SimpleTensor<qint16_t> &weights, const SimpleTensor<qint16_t> &bias, const TensorShape &dst_shape); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/FullyConnectedLayer.h b/tests/validation/CPP/FullyConnectedLayer.h new file mode 100644 index 0000000000..05c570a2c0 --- /dev/null +++ b/tests/validation/CPP/FullyConnectedLayer.h @@ -0,0 +1,44 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_H__ +#define __ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> fully_connected_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<T> &bias, const TensorShape &dst_shape); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_H__ */ diff --git a/tests/validation/CPP/GEMM.cpp b/tests/validation/CPP/GEMM.cpp new file mode 100644 index 0000000000..9b66597eb8 --- /dev/null +++ b/tests/validation/CPP/GEMM.cpp @@ -0,0 +1,122 @@ +/* + * 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 "GEMM.h" + +#include "tests/validation/FixedPoint.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type> +SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const SimpleTensor<T> &c, float alpha, float beta) +{ + // Create reference + SimpleTensor<T> dst{ c.shape(), c.data_type(), 1, c.fixed_point_position() }; + + // Compute reference + const int M = dst.shape().y(); + const int N = dst.shape().x(); + const int K = a.shape().x(); + + for(int row = 0; row < M; ++row) + { + for(int col = 0; col < N; ++col) + { + T acc(0); + + for(int k = 0; k < K; ++k) + { + acc += a[row * K + k] * b[k * N + col]; + } + + // Finalize the result: alpha * A * B + beta * C + dst[col + row * N] = alpha * acc + beta * c[col + row * N]; + } + } + + return dst; +} + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type> +SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const SimpleTensor<T> &c, float alpha, float beta) +{ + using namespace fixed_point_arithmetic; + + // Create reference + SimpleTensor<T> dst{ c.shape(), c.data_type(), 1, c.fixed_point_position() }; + + // Compute reference + using promoted_type = fixed_point_arithmetic::traits::promote_t<T>; + + const int M = dst.shape().y(); + const int N = dst.shape().x(); + const int K = a.shape().x(); + const int fixed_point_position = a.fixed_point_position(); + + const fixed_point<T> alpha_q(alpha, fixed_point_position); + const fixed_point<T> beta_q(beta, fixed_point_position); + + for(int row = 0; row < M; ++row) + { + for(int col = 0; col < N; ++col) + { + fixed_point<promoted_type> acc_q(0, fixed_point_position); + + for(int k = 0; k < K; ++k) + { + const fixed_point<promoted_type> a0_q(a[row * K + k], fixed_point_position, true); + const fixed_point<promoted_type> b0_q(b[k * N + col], fixed_point_position, true); + + acc_q = acc_q + (a0_q * b0_q); + } + + // Finalize the result: alpha * A * B + beta * C + const fixed_point<T> c0_q(c[col + row * N], fixed_point_position, true); + + fixed_point<T> res_q(acc_q); + res_q = alpha_q * res_q; + res_q = res_q + (beta_q * c0_q); + + // Store the result + dst[col + row * N] = res_q.raw(); + } + } + + return dst; +} + +template SimpleTensor<float> gemm(const SimpleTensor<float> &a, const SimpleTensor<float> &b, const SimpleTensor<float> &c, float alpha, float beta); +template SimpleTensor<half_float::half> gemm(const SimpleTensor<half_float::half> &a, const SimpleTensor<half_float::half> &b, const SimpleTensor<half_float::half> &c, float alpha, float beta); +template SimpleTensor<qint8_t> gemm(const SimpleTensor<qint8_t> &a, const SimpleTensor<qint8_t> &b, const SimpleTensor<qint8_t> &c, float alpha, float beta); +template SimpleTensor<qint16_t> gemm(const SimpleTensor<qint16_t> &a, const SimpleTensor<qint16_t> &b, const SimpleTensor<qint16_t> &c, float alpha, float beta); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/GEMM.h b/tests/validation/CPP/GEMM.h new file mode 100644 index 0000000000..cda792bf8b --- /dev/null +++ b/tests/validation/CPP/GEMM.h @@ -0,0 +1,47 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_GEMM_H__ +#define __ARM_COMPUTE_TEST_GEMM_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const SimpleTensor<T> &c, float alpha, float beta); + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const SimpleTensor<T> &c, float alpha, float beta); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_GEMM_H__ */ diff --git a/tests/validation/CPP/L2Normalize.cpp b/tests/validation/CPP/L2Normalize.cpp new file mode 100644 index 0000000000..4fb4d57eb4 --- /dev/null +++ b/tests/validation/CPP/L2Normalize.cpp @@ -0,0 +1,88 @@ +/* + * 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 "L2Normalize.h" +#include "ReductionOperation.h" + +#include "tests/validation/Helpers.h" + +#include <algorithm> +#include <cmath> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +namespace +{ +TensorShape get_output_shape(TensorShape shape, unsigned int axis) +{ + TensorShape output_shape(shape); + output_shape.set(axis, 1); + return output_shape; +} +} // namespace + +template <typename T> +SimpleTensor<T> l2_normalize(const SimpleTensor<T> &src, unsigned int axis, float epsilon) +{ + // Create reference + SimpleTensor<T> dst{ src.shape(), src.data_type() }; + + // Reduce across given axis + SimpleTensor<T> sum = reduction_operation(src, get_output_shape(src.shape(), axis), axis, ReductionOperation::SUM_SQUARE); + + // Compute reference + const int elems = src.shape()[axis]; + const int upper_dims = src.shape().total_size_upper(axis + 1); + + for(int du = 0; du < upper_dims; ++du) + { + if(axis == 0) + { + const T *src_row_ptr = src.data() + du * elems; + T *dst_row_ptr = dst.data() + du * elems; + const T normalization_value = std::sqrt(std::max(sum[du], epsilon)); + std::transform(src_row_ptr, src_row_ptr + elems, dst_row_ptr, [normalization_value](T val) + { + return val / normalization_value; + }); + } + else + { + ARM_COMPUTE_ERROR("Unsupported normalization axis"); + } + } + + return dst; +} + +template SimpleTensor<float> l2_normalize(const SimpleTensor<float> &src, unsigned int axis, float epsilon); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/L2Normalize.h b/tests/validation/CPP/L2Normalize.h new file mode 100644 index 0000000000..1db3ae6174 --- /dev/null +++ b/tests/validation/CPP/L2Normalize.h @@ -0,0 +1,44 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_L2NORMALIZE_H__ +#define __ARM_COMPUTE_TEST_L2NORMALIZE_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> l2_normalize(const SimpleTensor<T> &src, unsigned int axis, float epsilon); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_L2NORMALIZE_H__ */ diff --git a/tests/validation/CPP/MeanStdDev.cpp b/tests/validation/CPP/MeanStdDev.cpp new file mode 100644 index 0000000000..4a39b13d56 --- /dev/null +++ b/tests/validation/CPP/MeanStdDev.cpp @@ -0,0 +1,57 @@ +/* + * 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 "MeanStdDev.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +std::pair<float, float> mean_and_standard_deviation(const SimpleTensor<T> &in) +{ + const int num_elements = in.num_elements(); + + // Calculate mean + float mean = std::accumulate(in.data(), in.data() + num_elements, 0.f) / num_elements; + + // Calculate standard deviation + float std_dev = std::accumulate(in.data(), in.data() + num_elements, 0.f, [&mean](float a, float b) + { + return a + (mean - b) * (mean - b); + }); + + std_dev = std::sqrt(std_dev / num_elements); + + return std::make_pair(mean, std_dev); +} + +template std::pair<float, float> mean_and_standard_deviation(const SimpleTensor<uint8_t> &in); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/MeanStdDev.h b/tests/validation/CPP/MeanStdDev.h new file mode 100644 index 0000000000..6b89ae0656 --- /dev/null +++ b/tests/validation/CPP/MeanStdDev.h @@ -0,0 +1,43 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_STD_MEAN_DEV_H__ +#define __ARM_COMPUTE_TEST_STD_MEAN_DEV_H__ + +#include "tests/SimpleTensor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +std::pair<float, float> mean_and_standard_deviation(const SimpleTensor<T> &in); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_STD_MEAN_DEV_H__ */ diff --git a/tests/validation/CPP/NormalizationLayer.cpp b/tests/validation/CPP/NormalizationLayer.cpp new file mode 100644 index 0000000000..3c6f5e1a54 --- /dev/null +++ b/tests/validation/CPP/NormalizationLayer.cpp @@ -0,0 +1,275 @@ +/* + * 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 "NormalizationLayer.h" + +#include "tests/validation/FixedPoint.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type> +SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info) +{ + // Create reference + SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() }; + + // Compute reference + const uint32_t norm_size = info.norm_size(); + NormType type = info.type(); + float beta = info.beta(); + uint32_t kappa = info.kappa(); + + const int cols = src.shape()[0]; + const int rows = src.shape()[1]; + const int depth = src.shape()[2]; + int upper_dims = src.shape().total_size() / (cols * rows); + + float coeff = info.scale_coeff(); + int radius_cols = norm_size / 2; + + // IN_MAP_1D and CROSS_MAP normalize over a single axis only + int radius_rows = (NormType::IN_MAP_2D == type) ? norm_size / 2 : 0; + + if(type == NormType::CROSS_MAP) + { + // Remove also depth from upper dimensions since it is the dimension we + // want to use for normalization + upper_dims /= depth; + + for(int r = 0; r < upper_dims; ++r) + { + for(int i = 0; i < rows; ++i) + { + for(int k = 0; k < cols; ++k) + { + for(int l = 0; l < depth; ++l) + { + float accumulated_scale = 0.f; + + for(int j = -radius_cols; j <= radius_cols; ++j) + { + const int z = l + j; + + if(z >= 0 && z < depth) + { + const T value = src[k + i * cols + z * rows * cols + r * cols * rows * depth]; + accumulated_scale += value * value; + } + } + + dst[k + i * cols + l * rows * cols + r * cols * rows * depth] = kappa + accumulated_scale * coeff; + } + } + } + } + } + else + { + for(int r = 0; r < upper_dims; ++r) + { + for(int i = 0; i < rows; ++i) + { + for(int k = 0; k < cols; ++k) + { + float accumulated_scale = 0.f; + + for(int j = -radius_rows; j <= radius_rows; ++j) + { + const int y = i + j; + for(int l = -radius_cols; l <= radius_cols; ++l) + { + const int x = k + l; + + if((x >= 0 && y >= 0) && (x < cols && y < rows)) + { + const T value = src[x + y * cols + r * cols * rows]; + accumulated_scale += value * value; + } + } + } + + dst[k + i * cols + r * cols * rows] = kappa + accumulated_scale * coeff; + } + } + } + } + + if(beta == 1.f) + { + for(int i = 0; i < dst.num_elements(); ++i) + { + dst[i] = src[i] / dst[i]; + } + } + else if(beta == 0.5f) + { + for(int i = 0; i < dst.num_elements(); ++i) + { + dst[i] = src[i] / std::sqrt(dst[i]); + } + } + else + { + for(int i = 0; i < dst.num_elements(); ++i) + { + dst[i] = src[i] * std::exp(std::log(dst[i]) * -beta); + } + } + + return dst; +} + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type> +SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info) +{ + using namespace fixed_point_arithmetic; + + // Create reference + SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() }; + + // Compute reference + const int fixed_point_position = src.fixed_point_position(); + + const uint32_t norm_size = info.norm_size(); + NormType type = info.type(); + fixed_point<T> beta(info.beta(), fixed_point_position); + fixed_point<T> kappa(info.kappa(), fixed_point_position); + + const int cols = src.shape()[0]; + const int rows = src.shape()[1]; + const int depth = src.shape()[2]; + int upper_dims = src.shape().total_size() / (cols * rows); + + fixed_point<T> coeff(info.scale_coeff(), fixed_point_position); + int radius_cols = norm_size / 2; + + // IN_MAP_1D and CROSS_MAP normalize over a single axis only + int radius_rows = (NormType::IN_MAP_2D == type) ? norm_size / 2 : 0; + + if(type == NormType::CROSS_MAP) + { + // Remove also depth from upper dimensions since it is the dimension we + // want to use for normalization + upper_dims /= depth; + + for(int r = 0; r < upper_dims; ++r) + { + for(int i = 0; i < rows; ++i) + { + for(int k = 0; k < cols; ++k) + { + for(int l = 0; l < depth; ++l) + { + fixed_point<T> accumulated_scale(0.f, fixed_point_position); + + for(int j = -radius_cols; j <= radius_cols; ++j) + { + const int z = l + j; + + if(z >= 0 && z < depth) + { + const T value = src[k + i * cols + z * rows * cols + r * cols * rows * depth]; + const fixed_point<T> fp_value(value, fixed_point_position, true); + accumulated_scale = add(accumulated_scale, mul(fp_value, fp_value)); + } + } + + accumulated_scale = add(kappa, mul(accumulated_scale, coeff)); + dst[k + i * cols + l * rows * cols + r * cols * rows * depth] = accumulated_scale.raw(); + } + } + } + } + } + else + { + for(int r = 0; r < upper_dims; ++r) + { + for(int i = 0; i < rows; ++i) + { + for(int k = 0; k < cols; ++k) + { + fixed_point<T> accumulated_scale(0.f, fixed_point_position); + + for(int j = -radius_rows; j <= radius_rows; ++j) + { + const int y = i + j; + + for(int l = -radius_cols; l <= radius_cols; ++l) + { + const int x = k + l; + + if((x >= 0 && y >= 0) && (x < cols && y < rows)) + { + const T value = src[x + y * cols + r * cols * rows]; + const fixed_point<T> fp_value(value, fixed_point_position, true); + accumulated_scale = add(accumulated_scale, mul(fp_value, fp_value)); + } + } + } + + accumulated_scale = add(kappa, mul(accumulated_scale, coeff)); + dst[k + i * cols + r * cols * rows] = accumulated_scale.raw(); + } + } + } + } + + if(info.beta() == 1.f) + { + for(int i = 0; i < dst.num_elements(); ++i) + { + fixed_point<T> res = div(fixed_point<T>(src[i], fixed_point_position, true), fixed_point<T>(dst[i], fixed_point_position, true)); + dst[i] = res.raw(); + } + } + else + { + const fixed_point<T> beta(info.beta(), fixed_point_position); + + for(int i = 0; i < dst.num_elements(); ++i) + { + fixed_point<T> res = pow(fixed_point<T>(dst[i], fixed_point_position, true), beta); + res = div(fixed_point<T>(src[i], fixed_point_position, true), res); + dst[i] = res.raw(); + } + } + + return dst; +} + +template SimpleTensor<float> normalization_layer(const SimpleTensor<float> &src, NormalizationLayerInfo info); +template SimpleTensor<half_float::half> normalization_layer(const SimpleTensor<half_float::half> &src, NormalizationLayerInfo info); +template SimpleTensor<qint8_t> normalization_layer(const SimpleTensor<qint8_t> &src, NormalizationLayerInfo info); +template SimpleTensor<qint16_t> normalization_layer(const SimpleTensor<qint16_t> &src, NormalizationLayerInfo info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/NormalizationLayer.h b/tests/validation/CPP/NormalizationLayer.h new file mode 100644 index 0000000000..3f624ff30a --- /dev/null +++ b/tests/validation/CPP/NormalizationLayer.h @@ -0,0 +1,47 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_NORMALIZATION_LAYER_H__ +#define __ARM_COMPUTE_TEST_NORMALIZATION_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info); + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_NORMALIZATION_LAYER_H__ */ diff --git a/tests/validation/CPP/PoolingLayer.cpp b/tests/validation/CPP/PoolingLayer.cpp new file mode 100644 index 0000000000..c4425ca9a1 --- /dev/null +++ b/tests/validation/CPP/PoolingLayer.cpp @@ -0,0 +1,243 @@ +/* + * 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 "PoolingLayer.h" + +#include "tests/validation/FixedPoint.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +namespace +{ +TensorShape calculate_output_shape(TensorShape shape, PoolingLayerInfo info) +{ + TensorShape dst_shape = shape; + const std::pair<unsigned int, unsigned int> scaled_dims = arm_compute::scaled_dimensions(shape.x(), + shape.y(), + info.pool_size(), + info.pool_size(), + info.pad_stride_info()); + dst_shape.set(0, scaled_dims.first); + dst_shape.set(1, scaled_dims.second); + + return dst_shape; +} +} // namespace + +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type> +SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, PoolingLayerInfo info) +{ + const int pool_size = info.pool_size(); + PoolingType type = info.pool_type(); + int pool_stride_x = info.pad_stride_info().stride().first; + int pool_stride_y = info.pad_stride_info().stride().second; + int pad_x = info.pad_stride_info().pad().first; + int pad_y = info.pad_stride_info().pad().second; + + const auto w_src = static_cast<int>(src.shape()[0]); + const auto h_src = static_cast<int>(src.shape()[1]); + const int upper_dims = src.shape().total_size() / (w_src * h_src); + + // Create reference + SimpleTensor<T> dst{ calculate_output_shape(src.shape(), info), src.data_type(), 1, src.fixed_point_position() }; + + const auto w_dst = static_cast<int>(dst.shape()[0]); + const auto h_dst = static_cast<int>(dst.shape()[1]); + + if(type == PoolingType::MAX) + { + for(int r = 0; r < upper_dims; ++r) + { + for(int h = 0; h < h_dst; ++h) + { + for(int w = 0; w < w_dst; ++w) + { + int wstart = w * pool_stride_x - pad_x; + int hstart = h * pool_stride_y - pad_y; + int wend = std::min(wstart + pool_size, w_src); + int hend = std::min(hstart + pool_size, h_src); + wstart = std::max(wstart, 0); + hstart = std::max(hstart, 0); + + T max_val = std::numeric_limits<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]; + if(val > max_val) + { + max_val = val; + } + } + } + + dst[r * h_dst * w_dst + h * w_dst + w] = max_val; + } + } + } + } + else // Average pooling + { + for(int r = 0; r < upper_dims; ++r) + { + for(int h = 0; h < h_dst; ++h) + { + for(int w = 0; w < w_dst; ++w) + { + T avg_val(0); + int wstart = w * pool_stride_x - pad_x; + int hstart = h * pool_stride_y - pad_y; + int wend = std::min(wstart + pool_size, w_src + pad_x); + int hend = std::min(hstart + pool_size, h_src + pad_y); + 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); + + for(int y = hstart; y < hend; ++y) + { + for(int x = wstart; x < wend; ++x) + { + avg_val += src[r * h_src * w_src + y * w_src + x]; + } + } + dst[r * h_dst * w_dst + h * w_dst + w] = avg_val / pool; + } + } + } + } + + return dst; +} + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type> +SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, PoolingLayerInfo info) +{ + const int pool_size = info.pool_size(); + PoolingType type = info.pool_type(); + int pool_stride_x = info.pad_stride_info().stride().first; + int pool_stride_y = info.pad_stride_info().stride().second; + int pad_x = info.pad_stride_info().pad().first; + int pad_y = info.pad_stride_info().pad().second; + + const auto w_src = static_cast<int>(src.shape()[0]); + const auto h_src = static_cast<int>(src.shape()[1]); + const int upper_dims = src.shape().total_size() / (w_src * h_src); + + // Create reference + SimpleTensor<T> dst{ calculate_output_shape(src.shape(), info), src.data_type(), 1, src.fixed_point_position() }; + + const auto w_dst = static_cast<int>(dst.shape()[0]); + const auto h_dst = static_cast<int>(dst.shape()[1]); + + if(type == PoolingType::MAX) + { + for(int r = 0; r < upper_dims; ++r) + { + for(int h = 0; h < h_dst; ++h) + { + for(int w = 0; w < w_dst; ++w) + { + int wstart = w * pool_stride_x - pad_x; + int hstart = h * pool_stride_y - pad_y; + int wend = std::min(wstart + pool_size, w_src); + int hend = std::min(hstart + pool_size, h_src); + wstart = std::max(wstart, 0); + hstart = std::max(hstart, 0); + + T max_val = std::numeric_limits<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]; + if(val > max_val) + { + max_val = val; + } + } + } + + dst[r * h_dst * w_dst + h * w_dst + w] = max_val; + } + } + } + } + else // Average pooling + { + for(int r = 0; r < upper_dims; ++r) + { + for(int h = 0; h < h_dst; ++h) + { + for(int w = 0; w < w_dst; ++w) + { + int wstart = w * pool_stride_x - pad_x; + int hstart = h * pool_stride_y - pad_y; + int wend = std::min(wstart + pool_size, w_src + pad_x); + int hend = std::min(hstart + pool_size, h_src + pad_y); + 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); + + using namespace fixed_point_arithmetic; + + const int fixed_point_position = src.fixed_point_position(); + const fixed_point<T> invpool_fp(1.f / static_cast<float>(pool), fixed_point_position); + fixed_point<T> avg_val(0, fixed_point_position, true); + + for(int y = hstart; y < hend; ++y) + { + for(int x = wstart; x < wend; ++x) + { + const fixed_point<T> in_fp(src[r * h_src * w_src + y * w_src + x], fixed_point_position, true); + avg_val = add(avg_val, in_fp); + } + } + dst[r * h_dst * w_dst + h * w_dst + w] = mul(avg_val, invpool_fp).raw(); + } + } + } + } + + return dst; +} + +template SimpleTensor<float> pooling_layer(const SimpleTensor<float> &src, PoolingLayerInfo info); +template SimpleTensor<half_float::half> pooling_layer(const SimpleTensor<half_float::half> &src, PoolingLayerInfo info); +template SimpleTensor<qint8_t> pooling_layer(const SimpleTensor<qint8_t> &src, PoolingLayerInfo info); +template SimpleTensor<qint16_t> pooling_layer(const SimpleTensor<qint16_t> &src, PoolingLayerInfo info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/PoolingLayer.h b/tests/validation/CPP/PoolingLayer.h new file mode 100644 index 0000000000..334054a0eb --- /dev/null +++ b/tests/validation/CPP/PoolingLayer.h @@ -0,0 +1,47 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_POOLING_LAYER_H__ +#define __ARM_COMPUTE_TEST_POOLING_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, PoolingLayerInfo info); + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, PoolingLayerInfo info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_POOLING_LAYER_H__ */ diff --git a/tests/validation/CPP/QuantizationLayer.cpp b/tests/validation/CPP/QuantizationLayer.cpp new file mode 100644 index 0000000000..d61e75a3a9 --- /dev/null +++ b/tests/validation/CPP/QuantizationLayer.cpp @@ -0,0 +1,85 @@ +/* + * 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 "QuantizationLayer.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +void compute_min_max(const SimpleTensor<float> &src, float *min, float *max) +{ + // Set min and max to first pixel + float tmp_min = src[0]; + float tmp_max = src[0]; + + // Look for min and max values + for(int i = 1; i < src.num_elements(); ++i) + { + if(src[i] < tmp_min) + { + tmp_min = src[i]; + } + if(src[i] > tmp_max) + { + tmp_max = src[i]; + } + } + + *min = tmp_min; + *max = tmp_max; +} + +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type> +SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<T> &src) +{ + // Create reference + SimpleTensor<uint8_t> dst{ src.shape(), DataType::U8 }; + + // Compute min and max of the tensor using Min-Max layer + float min = 0.f; + float max = 0.f; + + compute_min_max(src, &min, &max); + + const float range = max - min; + + for(int i = 0; i < src.num_elements(); ++i) + { + // map values to range [0.0, 1.0] + const float normalized = (src[i] - min) / range; + dst[i] = static_cast<uint8_t>(std::min(255.0f, normalized * 256.0f)); + } + + return dst; +} + +template SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<float> &src); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/QuantizationLayer.h b/tests/validation/CPP/QuantizationLayer.h new file mode 100644 index 0000000000..7c5572ccf8 --- /dev/null +++ b/tests/validation/CPP/QuantizationLayer.h @@ -0,0 +1,44 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_QUANTIZATION_LAYER_H__ +#define __ARM_COMPUTE_TEST_QUANTIZATION_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<T> &src); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_QUANTIZATION_LAYER_H__ */ diff --git a/tests/validation/CPP/ReductionOperation.cpp b/tests/validation/CPP/ReductionOperation.cpp new file mode 100644 index 0000000000..acfcc09cea --- /dev/null +++ b/tests/validation/CPP/ReductionOperation.cpp @@ -0,0 +1,93 @@ +/* + * 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 "ReductionOperation.h" + +#include "tests/validation/Helpers.h" + +#include <algorithm> +#include <cmath> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +namespace +{ +template <typename T> +struct square +{ + T operator()(const T &lhs, const T &rhs) const + { + return (lhs + rhs * rhs); + } +}; + +template <typename T> +T reduce_operation(T *ptr, int reduce_elements, ReductionOperation op) +{ + switch(op) + { + case ReductionOperation::SUM_SQUARE: + return std::accumulate(ptr, ptr + reduce_elements, 0.f, square<T>()); + default: + ARM_COMPUTE_ERROR("Unsupported reduction operation"); + } +} +} // namespace + +template <typename T> +SimpleTensor<T> reduction_operation(const SimpleTensor<T> &src, const TensorShape &dst_shape, unsigned int axis, ReductionOperation op) +{ + // Create reference + SimpleTensor<T> dst{ dst_shape, src.data_type() }; + + // Compute reference + const int reduce_elems = src.shape()[axis]; + const int upper_dims = src.shape().total_size_upper(axis + 1); + + for(int du = 0; du < upper_dims; ++du) + { + if(axis == 0) + { + const T *src_row_ptr = src.data() + du * reduce_elems; + dst[du] = reduce_operation(src_row_ptr, reduce_elems, op); + } + else + { + ARM_COMPUTE_ERROR("Unsupported reduction axis"); + } + } + + return dst; +} + +template SimpleTensor<float> reduction_operation(const SimpleTensor<float> &src, const TensorShape &dst_shape, unsigned int axis, ReductionOperation op); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/ReductionOperation.h b/tests/validation/CPP/ReductionOperation.h new file mode 100644 index 0000000000..6da6436686 --- /dev/null +++ b/tests/validation/CPP/ReductionOperation.h @@ -0,0 +1,44 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_REDUCTION_OPERATION_H__ +#define __ARM_COMPUTE_TEST_REDUCTION_OPERATION_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> reduction_operation(const SimpleTensor<T> &src, const TensorShape &dst_shape, unsigned int axis, ReductionOperation op); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_FLOOR_H__ */ diff --git a/tests/validation/CPP/Scale.cpp b/tests/validation/CPP/Scale.cpp new file mode 100644 index 0000000000..a1119f33b9 --- /dev/null +++ b/tests/validation/CPP/Scale.cpp @@ -0,0 +1,166 @@ +/* + * 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 "arm_compute/core/Helpers.h" + +#include "Scale.h" +#include "Utils.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> scale(const SimpleTensor<T> &in, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value) +{ + TensorShape shape_scaled(in.shape()); + shape_scaled.set(0, in.shape()[0] * scale_x); + shape_scaled.set(1, in.shape()[1] * scale_y); + SimpleTensor<T> out(shape_scaled, in.data_type()); + + // Compute the ratio between source width/height and destination width/height + const auto wr = static_cast<float>(in.shape()[0]) / static_cast<float>(out.shape()[0]); + const auto hr = static_cast<float>(in.shape()[1]) / static_cast<float>(out.shape()[1]); + + const auto width = static_cast<int>(in.shape().x()); + const auto height = static_cast<int>(in.shape().y()); + + // Area interpolation behaves as Nearest Neighbour in case of up-sampling + if(policy == InterpolationPolicy::AREA && wr <= 1.f && hr <= 1.f) + { + policy = InterpolationPolicy::NEAREST_NEIGHBOR; + } + + for(int element_idx = 0, count = 0; element_idx < out.num_elements(); ++element_idx, ++count) + { + Coordinates id = index2coord(out.shape(), element_idx); + int idx = id.x(); + int idy = id.y(); + float x_src = (idx + 0.5f) * wr - 0.5f; + float y_src = (idy + 0.5f) * hr - 0.5f; + + switch(policy) + { + case InterpolationPolicy::NEAREST_NEIGHBOR: + { + //Calculate the source coords without -0.5f is equivalent to round the x_scr/y_src coords + x_src = (idx + 0.5f) * wr; + y_src = (idy + 0.5f) * hr; + id.set(0, x_src); + id.set(1, y_src); + + // If coordinates in range of tensor's width or height + if(x_src >= -1 || y_src >= -1 || x_src <= width || y_src <= height) + { + out[element_idx] = tensor_elem_at(in, id, border_mode, constant_border_value); + } + else + { + if(border_mode == BorderMode::CONSTANT) + { + out[element_idx] = constant_border_value; + } + else if(border_mode == BorderMode::REPLICATE) + { + id.set(0, clamp(static_cast<int>(x_src), 0, width - 1)); + id.set(1, clamp(static_cast<int>(y_src), 0, height - 1)); + out[element_idx] = in[coord2index(in.shape(), id)]; + } + } + break; + } + case InterpolationPolicy::BILINEAR: + { + id.set(0, std::floor(x_src)); + id.set(1, std::floor(y_src)); + if(x_src >= -1 || y_src >= -1 || x_src <= width || y_src <= height) + { + out[element_idx] = bilinear_policy(in, id, x_src, y_src, border_mode, constant_border_value); + } + else + { + if(border_mode == BorderMode::CONSTANT) + { + out[element_idx] = constant_border_value; + } + else if(border_mode == BorderMode::REPLICATE) + { + id.set(0, clamp(static_cast<int>(x_src), 0, width - 1)); + id.set(1, clamp(static_cast<int>(y_src), 0, height - 1)); + out[element_idx] = in[coord2index(in.shape(), id)]; + } + } + break; + } + case InterpolationPolicy::AREA: + { + int x_from = std::floor(idx * wr - 0.5f - x_src); + int y_from = std::floor(idy * hr - 0.5f - y_src); + int x_to = std::ceil((idx + 1) * wr - 0.5f - x_src); + int y_to = std::ceil((idy + 1) * hr - 0.5f - y_src); + const int xi = std::floor(x_src); + const int yi = std::floor(y_src); + + // Clamp position to borders + x_src = std::max(-1.f, std::min(x_src, static_cast<float>(width))); + y_src = std::max(-1.f, std::min(y_src, static_cast<float>(height))); + + // Clamp bounding box offsets to borders + x_from = ((x_src + x_from) < -1) ? -1 : x_from; + y_from = ((y_src + y_from) < -1) ? -1 : y_from; + x_to = ((x_src + x_to) > width) ? (width - x_src) : x_to; + y_to = ((y_src + y_to) > height) ? (height - y_src) : y_to; + ARM_COMPUTE_ERROR_ON((x_to - x_from + 1) == 0 || (y_to - y_from + 1) == 0); + + float sum = 0; + for(int j = yi + y_from, je = yi + y_to; j <= je; ++j) + { + for(int i = xi + x_from, ie = xi + x_to; i <= ie; ++i) + { + id.set(0, static_cast<int>(i)); + id.set(1, static_cast<int>(j)); + sum += tensor_elem_at(in, id, border_mode, constant_border_value); + } + } + out[element_idx] = sum / ((x_to - x_from + 1) * (y_to - y_from + 1)); + + break; + } + default: + ARM_COMPUTE_ERROR("Unsupported interpolation mode"); + } + } + + return out; +} + +template SimpleTensor<uint8_t> scale(const SimpleTensor<uint8_t> &src, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute
\ No newline at end of file diff --git a/tests/validation/CPP/Scale.h b/tests/validation/CPP/Scale.h new file mode 100644 index 0000000000..b882915946 --- /dev/null +++ b/tests/validation/CPP/Scale.h @@ -0,0 +1,43 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_SCALE_H__ +#define __ARM_COMPUTE_TEST_SCALE_H__ + +#include "tests/SimpleTensor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T> +SimpleTensor<T> scale(const SimpleTensor<T> &in, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value = 0); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_SCALE_H__ */ diff --git a/tests/validation/CPP/SoftmaxLayer.cpp b/tests/validation/CPP/SoftmaxLayer.cpp new file mode 100644 index 0000000000..4fe87d07dc --- /dev/null +++ b/tests/validation/CPP/SoftmaxLayer.cpp @@ -0,0 +1,122 @@ +/* + * 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 "SoftmaxLayer.h" + +#include "tests/validation/FixedPoint.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type> +SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src) +{ + // Create reference + SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() }; + + // Compute reference + const int cols = src.shape()[0]; + const int upper_dims = src.num_elements() / cols; + + for(int r = 0; r < upper_dims; ++r) + { + const T *src_row_ptr = src.data() + r * cols; + T *dst_row_ptr = dst.data() + r * cols; + + // Find max + const T max = *std::max_element(src_row_ptr, src_row_ptr + cols); + + // Regularize + T sum(0.f); + std::transform(src_row_ptr, src_row_ptr + cols, dst_row_ptr, [&sum, max](T val) + { + const T res(std::exp(val - max)); + sum += res; + return res; + }); + + // Normalize + std::transform(dst_row_ptr, dst_row_ptr + cols, dst_row_ptr, [sum](T val) + { + return val / sum; + }); + } + + return dst; +} + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type> +SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src) +{ + using namespace fixed_point_arithmetic; + + // Create reference + SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() }; + + // Compute reference + const int cols = src.shape()[0]; + const int upper_dims = src.num_elements() / cols; + + for(int r = 0; r < upper_dims; ++r) + { + const T *src_row_ptr = src.data() + r * cols; + T *dst_row_ptr = dst.data() + r * cols; + + // Find max + const fixed_point<T> max(*std::max_element(src_row_ptr, src_row_ptr + cols), src.fixed_point_position(), true); + + // Regularize + using promoted_type = fixed_point_arithmetic::traits::promote_t<T>; + fixed_point<promoted_type> sum(0, src.fixed_point_position(), true); + std::transform(src_row_ptr, src_row_ptr + cols, dst_row_ptr, [&](T val) + { + const fixed_point<T> res = exp(fixed_point<T>(val, src.fixed_point_position(), true) - max); + sum = add(sum, fixed_point<promoted_type>(res.raw(), src.fixed_point_position(), true)); + return res.raw(); + }); + + // Normalize + fixed_point<T> saturated_sum(sum); + std::transform(dst_row_ptr, dst_row_ptr + cols, dst_row_ptr, [&](T val) + { + return div(fixed_point<T>(val, src.fixed_point_position(), true), saturated_sum).raw(); + }); + } + + return dst; +} + +template SimpleTensor<float> softmax_layer(const SimpleTensor<float> &src); +template SimpleTensor<half_float::half> softmax_layer(const SimpleTensor<half_float::half> &src); +template SimpleTensor<qint8_t> softmax_layer(const SimpleTensor<qint8_t> &src); +template SimpleTensor<qint16_t> softmax_layer(const SimpleTensor<qint16_t> &src); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/SoftmaxLayer.h b/tests/validation/CPP/SoftmaxLayer.h new file mode 100644 index 0000000000..ab79bc4850 --- /dev/null +++ b/tests/validation/CPP/SoftmaxLayer.h @@ -0,0 +1,47 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_SOFTMAX_LAYER_H__ +#define __ARM_COMPUTE_TEST_SOFTMAX_LAYER_H__ + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0> +SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src); + +template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_SOFTMAX_LAYER_H__ */ diff --git a/tests/validation/CPP/Utils.cpp b/tests/validation/CPP/Utils.cpp new file mode 100644 index 0000000000..05443eabae --- /dev/null +++ b/tests/validation/CPP/Utils.cpp @@ -0,0 +1,93 @@ +/* + * 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 "Utils.h" + +#include "tests/validation/Helpers.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +// Return a tensor element at a specified coordinate with different border modes +template <typename T> +T tensor_elem_at(const SimpleTensor<T> &in, Coordinates coord, BorderMode border_mode, T constant_border_value) +{ + const int x = coord.x(); + const int y = coord.y(); + const auto width = static_cast<int>(in.shape().x()); + const auto height = static_cast<int>(in.shape().y()); + + // If coordinates beyond range of tensor's width or height + if(x < 0 || y < 0 || x >= width || y >= height) + { + if(border_mode == BorderMode::REPLICATE) + { + coord.set(0, std::max(0, std::min(x, width - 1))); + coord.set(1, std::max(0, std::min(y, height - 1))); + } + else + { + return constant_border_value; + } + } + return in[coord2index(in.shape(), coord)]; +} +template float tensor_elem_at(const SimpleTensor<float> &in, Coordinates coord, BorderMode border_mode, float constant_border_value); +template uint8_t tensor_elem_at(const SimpleTensor<uint8_t> &in, Coordinates coord, BorderMode border_mode, uint8_t constant_border_value); + +// Return the bilinear value at a specified coordinate with different border modes +template <typename T> +T bilinear_policy(const SimpleTensor<T> &in, Coordinates id, float xn, float yn, BorderMode border_mode, uint8_t constant_border_value) +{ + int idx = std::floor(xn); + int idy = std::floor(yn); + + const float dx = xn - idx; + const float dy = yn - idy; + const float dx_1 = 1.0f - dx; + const float dy_1 = 1.0f - dy; + + id.set(0, idx); + id.set(1, idy); + const T tl = tensor_elem_at(in, id, border_mode, constant_border_value); + id.set(0, idx + 1); + id.set(1, idy); + const T tr = tensor_elem_at(in, id, border_mode, constant_border_value); + id.set(0, idx); + id.set(1, idy + 1); + const T bl = tensor_elem_at(in, id, border_mode, constant_border_value); + id.set(0, idx + 1); + id.set(1, idy + 1); + const T br = tensor_elem_at(in, id, border_mode, constant_border_value); + + return tl * (dx_1 * dy_1) + tr * (dx * dy_1) + bl * (dx_1 * dy) + br * (dx * dy); +} +template uint8_t bilinear_policy(const SimpleTensor<uint8_t> &in, Coordinates id, float xn, float yn, BorderMode border_mode, uint8_t constant_border_value); + +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/CPP/Utils.h b/tests/validation/CPP/Utils.h new file mode 100644 index 0000000000..5e9ec822a5 --- /dev/null +++ b/tests/validation/CPP/Utils.h @@ -0,0 +1,52 @@ +/* + * 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. + */ +#ifndef __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__ +#define __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__ + +#include "arm_compute/core/Types.h" +#include "tests/Globals.h" +#include "tests/ILutAccessor.h" +#include "tests/Types.h" + +#include <array> +#include <random> +#include <type_traits> +#include <utility> +#include <vector> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename T> +T tensor_elem_at(const SimpleTensor<T> &in, Coordinates coord, BorderMode border_mode, T constant_border_value); + +template <typename T> +T bilinear_policy(const SimpleTensor<T> &in, Coordinates id, float xn, float yn, BorderMode border_mode, uint8_t constant_border_value); +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__ */ diff --git a/tests/validation/Datasets.h b/tests/validation/Datasets.h deleted file mode 100644 index 15e1b098e6..0000000000 --- a/tests/validation/Datasets.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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. - */ -#ifndef __ARM_COMPUTE_TEST_VALIDATION_DATASETS_H__ -#define __ARM_COMPUTE_TEST_VALIDATION_DATASETS_H__ - -#include "dataset/ActivationFunctionDataset.h" -#include "dataset/BatchNormalizationLayerDataset.h" -#include "dataset/BorderModeDataset.h" -#include "dataset/ConvertPolicyDataset.h" -#include "dataset/ConvolutionLayerDataset.h" -#include "dataset/DataTypeDatasets.h" -#include "dataset/FullyConnectedLayerDataset.h" -#include "dataset/GEMMDataset.h" -#include "dataset/ImageDatasets.h" -#include "dataset/InterpolationPolicyDataset.h" -#include "dataset/MatrixPatternDataset.h" -#include "dataset/NonLinearFilterFunctionDataset.h" -#include "dataset/NormalizationTypeDataset.h" -#include "dataset/PoolingTypesDataset.h" -#include "dataset/RoundingPolicyDataset.h" -#include "dataset/ShapeDatasets.h" -#include "dataset/ThresholdDataset.h" - -#include "boost_wrapper.h" - -using namespace boost::unit_test::data::monomorphic; - -namespace boost -{ -namespace unit_test -{ -namespace data -{ -namespace monomorphic -{ -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::SmallImages> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::LargeImages> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::SmallShapes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -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_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::UnsignedDataTypes> : boost::mpl::true_ -{ -}; - -// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::SignedDataTypes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::FloatDataTypes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::FixedPointDataTypes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::CNNFloatDataTypes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::CNNFixedPointDataTypes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::CNNDataTypes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::ActivationFunctions> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::BorderModes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::ConvertPolicies> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::InterpolationPolicies> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::NormalizationTypes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::RoundingPolicies> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::PoolingTypes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::AlexNetConvolutionLayerDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::AlexNetFullyConnectedLayerDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::DirectConvolutionShapes> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::SmallFullyConnectedLayerDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::LargeFullyConnectedLayerDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::SmallConvolutionLayerDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::SmallGEMMDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::LargeGEMMDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::RandomBatchNormalizationLayerDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::ThresholdDataset> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::NonLinearFilterFunctions> : boost::mpl::true_ -{ -}; - -/// Register the data set with Boost -template <> -struct is_dataset<arm_compute::test::MatrixPatterns> : boost::mpl::true_ -{ -}; -} -} -} -} -#endif /* __ARM_COMPUTE_TEST_VALIDATION_DATASETS_H__ */ diff --git a/tests/validation/FixedPoint.h b/tests/validation/FixedPoint.h index 12ffcdfc3d..9691e2a037 100644 --- a/tests/validation/FixedPoint.h +++ b/tests/validation/FixedPoint.h @@ -24,8 +24,8 @@ #ifndef __ARM_COMPUTE_TEST_VALIDATION_FIXEDPOINT_H__ #define __ARM_COMPUTE_TEST_VALIDATION_FIXEDPOINT_H__ -#include "Utils.h" #include "support/ToolchainSupport.h" +#include "tests/Utils.h" #include <cassert> #include <cstdint> @@ -63,6 +63,8 @@ template <> struct promote<uint32_t> { using type = uint64_t; }; template <> struct promote<int32_t> { using type = int64_t; }; template <> struct promote<uint64_t> { using type = uint64_t; }; template <> struct promote<int64_t> { using type = int64_t; }; +template <typename T> +using promote_t = typename promote<T>::type; // clang-format on // *INDENT-ON* } @@ -88,10 +90,6 @@ public: // Static Checks static_assert(std::is_integral<T>::value, "Type is not an integer"); - // Friends - friend struct detail::functions; - friend struct detail::constant_expr<T>; - /** Constructor (from different fixed point type) * * @param[in] val Fixed point @@ -387,7 +385,7 @@ struct functions template <typename T> static bool signbit(fixed_point<T> x) { - return ((x._value >> std::numeric_limits<T>::digits) != 0); + return ((x.raw() >> std::numeric_limits<T>::digits) != 0); } /** Checks if two fixed point numbers are equal * @@ -399,10 +397,10 @@ struct functions template <typename T> static bool isequal(fixed_point<T> x, fixed_point<T> y) { - uint8_t p = std::min(x._fixed_point_position, y._fixed_point_position); + uint8_t p = std::min(x.precision(), y.precision()); x.rescale(p); y.rescale(p); - return (x._value == y._value); + return (x.raw() == y.raw()); } /** Checks if two fixed point number are not equal * @@ -426,10 +424,10 @@ struct functions template <typename T> static bool isgreater(fixed_point<T> x, fixed_point<T> y) { - uint8_t p = std::min(x._fixed_point_position, y._fixed_point_position); + uint8_t p = std::min(x.precision(), y.precision()); x.rescale(p); y.rescale(p); - return (x._value > y._value); + return (x.raw() > y.raw()); } /** Checks if one fixed point is greater or equal than the other * @@ -441,10 +439,10 @@ struct functions template <typename T> static bool isgreaterequal(fixed_point<T> x, fixed_point<T> y) { - uint8_t p = std::min(x._fixed_point_position, y._fixed_point_position); + uint8_t p = std::min(x.precision(), y.precision()); x.rescale(p); y.rescale(p); - return (x._value >= y._value); + return (x.raw() >= y.raw()); } /** Checks if one fixed point is less than the other * @@ -456,10 +454,10 @@ struct functions template <typename T> static bool isless(fixed_point<T> x, fixed_point<T> y) { - uint8_t p = std::min(x._fixed_point_position, y._fixed_point_position); + uint8_t p = std::min(x.precision(), y.precision()); x.rescale(p); y.rescale(p); - return (x._value < y._value); + return (x.raw() < y.raw()); } /** Checks if one fixed point is less or equal than the other * @@ -471,10 +469,10 @@ struct functions template <typename T> static bool islessequal(fixed_point<T> x, fixed_point<T> y) { - uint8_t p = std::min(x._fixed_point_position, y._fixed_point_position); + uint8_t p = std::min(x.precision(), y.precision()); x.rescale(p); y.rescale(p); - return (x._value <= y._value); + return (x.raw() <= y.raw()); } /** Checks if one fixed point is less or greater than the other * @@ -499,7 +497,7 @@ struct functions template <typename T> static fixed_point<T> clamp(fixed_point<T> x, T min, T max) { - return fixed_point<T>(constant_expr<T>::clamp(x._value, min, max), x._fixed_point_position, true); + return fixed_point<T>(constant_expr<T>::clamp(x.raw(), min, max), x.precision(), true); } /** Negate number * @@ -511,12 +509,12 @@ struct functions static fixed_point<T> negate(fixed_point<T> x) { using promoted_T = typename traits::promote<T>::type; - promoted_T val = -x._value; + promoted_T val = -x.raw(); if(OP == OverflowPolicy::SATURATE) { val = constant_expr<T>::saturate_cast(val); } - return fixed_point<T>(static_cast<T>(val), x._fixed_point_position, true); + return fixed_point<T>(static_cast<T>(val), x.precision(), true); } /** Perform addition among two fixed point numbers * @@ -528,19 +526,19 @@ struct functions template <OverflowPolicy OP = OverflowPolicy::SATURATE, typename T> static fixed_point<T> add(fixed_point<T> x, fixed_point<T> y) { - uint8_t p = std::min(x._fixed_point_position, y._fixed_point_position); + uint8_t p = std::min(x.precision(), y.precision()); x.rescale(p); y.rescale(p); if(OP == OverflowPolicy::SATURATE) { using type = typename traits::promote<T>::type; - type val = static_cast<type>(x._value) + static_cast<type>(y._value); + type val = static_cast<type>(x.raw()) + static_cast<type>(y.raw()); val = constant_expr<T>::saturate_cast(val); return fixed_point<T>(static_cast<T>(val), p, true); } else { - return fixed_point<T>(x._value + y._value, p, true); + return fixed_point<T>(x.raw() + y.raw(), p, true); } } /** Perform subtraction among two fixed point numbers @@ -553,19 +551,19 @@ struct functions template <OverflowPolicy OP = OverflowPolicy::SATURATE, typename T> static fixed_point<T> sub(fixed_point<T> x, fixed_point<T> y) { - uint8_t p = std::min(x._fixed_point_position, y._fixed_point_position); + uint8_t p = std::min(x.precision(), y.precision()); x.rescale(p); y.rescale(p); if(OP == OverflowPolicy::SATURATE) { using type = typename traits::promote<T>::type; - type val = static_cast<type>(x._value) - static_cast<type>(y._value); + type val = static_cast<type>(x.raw()) - static_cast<type>(y.raw()); val = constant_expr<T>::saturate_cast(val); return fixed_point<T>(static_cast<T>(val), p, true); } else { - return fixed_point<T>(x._value - y._value, p, true); + return fixed_point<T>(x.raw() - y.raw(), p, true); } } /** Perform multiplication among two fixed point numbers @@ -579,10 +577,10 @@ struct functions static fixed_point<T> mul(fixed_point<T> x, fixed_point<T> y) { using promoted_T = typename traits::promote<T>::type; - uint8_t p_min = std::min(x._fixed_point_position, y._fixed_point_position); - uint8_t p_max = std::max(x._fixed_point_position, y._fixed_point_position); + uint8_t p_min = std::min(x.precision(), y.precision()); + uint8_t p_max = std::max(x.precision(), y.precision()); promoted_T round_factor = (1 << (p_max - 1)); - promoted_T val = ((static_cast<promoted_T>(x._value) * static_cast<promoted_T>(y._value)) + round_factor) >> p_max; + promoted_T val = ((static_cast<promoted_T>(x.raw()) * static_cast<promoted_T>(y.raw())) + round_factor) >> p_max; if(OP == OverflowPolicy::SATURATE) { val = constant_expr<T>::saturate_cast(val); @@ -600,11 +598,11 @@ struct functions static fixed_point<T> div(fixed_point<T> x, fixed_point<T> y) { using promoted_T = typename traits::promote<T>::type; - uint8_t p = std::min(x._fixed_point_position, y._fixed_point_position); - promoted_T denom = static_cast<promoted_T>(y._value); + uint8_t p = std::min(x.precision(), y.precision()); + promoted_T denom = static_cast<promoted_T>(y.raw()); if(denom != 0) { - promoted_T val = (static_cast<promoted_T>(x._value) << std::max(x._fixed_point_position, y._fixed_point_position)) / denom; + promoted_T val = (static_cast<promoted_T>(x.raw()) << std::max(x.precision(), y.precision())) / denom; if(OP == OverflowPolicy::SATURATE) { val = constant_expr<T>::saturate_cast(val); @@ -613,7 +611,7 @@ struct functions } else { - T val = (x._value < 0) ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max(); + T val = (x.raw() < 0) ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max(); return fixed_point<T>(val, p, true); } } @@ -628,12 +626,12 @@ struct functions static fixed_point<T> shift_left(fixed_point<T> x, size_t shift) { using promoted_T = typename traits::promote<T>::type; - promoted_T val = static_cast<promoted_T>(x._value) << shift; + promoted_T val = static_cast<promoted_T>(x.raw()) << shift; if(OP == OverflowPolicy::SATURATE) { val = constant_expr<T>::saturate_cast(val); } - return fixed_point<T>(static_cast<T>(val), x._fixed_point_position, true); + return fixed_point<T>(static_cast<T>(val), x.precision(), true); } /** Shift right * @@ -645,7 +643,7 @@ struct functions template <typename T> static fixed_point<T> shift_right(fixed_point<T> x, size_t shift) { - return fixed_point<T>(x._value >> shift, x._fixed_point_position, true); + return fixed_point<T>(x.raw() >> shift, x.precision(), true); } /** Calculate absolute value * @@ -657,8 +655,8 @@ struct functions static fixed_point<T> abs(fixed_point<T> x) { using promoted_T = typename traits::promote<T>::type; - T val = (x._value < 0) ? constant_expr<T>::saturate_cast(-static_cast<promoted_T>(x._value)) : x._value; - return fixed_point<T>(val, x._fixed_point_position, true); + T val = (x.raw() < 0) ? constant_expr<T>::saturate_cast(-static_cast<promoted_T>(x.raw())) : x.raw(); + return fixed_point<T>(val, x.precision(), true); } /** Calculate the logarithm of a fixed point number * @@ -669,7 +667,7 @@ struct functions template <typename T> static fixed_point<T> log(fixed_point<T> x) { - uint8_t p = x._fixed_point_position; + uint8_t p = x.precision(); auto const_one = fixed_point<T>(static_cast<T>(1), p); // Logarithm of 1 is zero and logarithm of negative values is not defined in R, so return 0. @@ -684,7 +682,7 @@ struct functions } // Remove even powers of 2 - T shift_val = 31 - __builtin_clz(x._value >> p); + T shift_val = 31 - __builtin_clz(x.raw() >> p); x = shift_right(x, shift_val); x = sub(x, const_one); @@ -716,7 +714,7 @@ struct functions template <typename T> static fixed_point<T> exp(fixed_point<T> x) { - uint8_t p = x._fixed_point_position; + uint8_t p = x.precision(); // Constants auto const_one = fixed_point<T>(1, p); auto ln2 = fixed_point<T>(0.6931471, p); @@ -726,7 +724,7 @@ struct functions auto C = fixed_point<T>(0.1763723, p); auto D = fixed_point<T>(0.0435108, p); - T scaled_int_part = detail::constant_expr<T>::to_int(mul(x, inv_ln2)._value, p); + T scaled_int_part = detail::constant_expr<T>::to_int(mul(x, inv_ln2).raw(), p); // Polynomial expansion auto frac_part = sub(x, mul(ln2, fixed_point<T>(scaled_int_part, p))); @@ -753,8 +751,8 @@ struct functions template <typename T> static fixed_point<T> inv_sqrt(fixed_point<T> x) { - const uint8_t p = x._fixed_point_position; - int8_t shift = std::numeric_limits<T>::digits - (p + detail::clz(x._value)); + const uint8_t p = x.precision(); + int8_t shift = std::numeric_limits<T>::digits - (p + detail::clz(x.raw())); shift += std::numeric_limits<T>::is_signed ? 1 : 0; @@ -784,7 +782,7 @@ struct functions template <typename T> static fixed_point<T> tanh(fixed_point<T> x) { - uint8_t p = x._fixed_point_position; + uint8_t p = x.precision(); // Constants auto const_one = fixed_point<T>(1, p); auto const_two = fixed_point<T>(2, p); diff --git a/tests/validation/Helpers.cpp b/tests/validation/Helpers.cpp new file mode 100644 index 0000000000..d3bcbbd9e4 --- /dev/null +++ b/tests/validation/Helpers.cpp @@ -0,0 +1,57 @@ +/* + * 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 "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TensorShape calculate_depth_concatenate_shape(const std::vector<TensorShape> &input_shapes) +{ + ARM_COMPUTE_ERROR_ON(input_shapes.empty()); + + TensorShape out_shape = input_shapes[0]; + + size_t max_x = 0; + size_t max_y = 0; + size_t depth = 0; + + for(const auto &shape : input_shapes) + { + max_x = std::max(shape.x(), max_x); + max_y = std::max(shape.y(), max_y); + depth += shape.z(); + } + + out_shape.set(0, max_x); + out_shape.set(1, max_y); + out_shape.set(2, depth); + + return out_shape; +} +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/Helpers.h b/tests/validation/Helpers.h index 19a0c4105c..30959161bb 100644 --- a/tests/validation/Helpers.h +++ b/tests/validation/Helpers.h @@ -25,18 +25,12 @@ #define __ARM_COMPUTE_TEST_VALIDATION_HELPERS_H__ #include "arm_compute/core/Types.h" -#include "tests/Globals.h" -#include "tests/ILutAccessor.h" -#include "tests/Types.h" -#include "tests/validation/ValidationUserConfiguration.h" +#include "arm_compute/core/Utils.h" #include "tests/validation/half.h" -#include <array> -#include <cstring> #include <random> #include <type_traits> #include <utility> -#include <vector> namespace arm_compute { @@ -44,158 +38,95 @@ namespace test { namespace validation { -/** Helper function to fill one or more tensors with the uniform distribution with int values. - * - * @param[in] dist Distribution to be used to get the values for the tensor. - * @param[in] seeds List of seeds to be used to fill each tensor. - * @param[in,out] tensor Tensor to be initialized with the values of the distribution. - * @param[in,out] other_tensors (Optional) One or more tensors to be filled. - * - */ -template <typename D, typename T, typename... Ts> -void fill_tensors(D &&dist, std::initializer_list<int> seeds, T &&tensor, Ts &&... other_tensors) +template <typename T> +struct is_floating_point : public std::is_floating_point<T> { - const std::array < T, 1 + sizeof...(Ts) > tensors{ { std::forward<T>(tensor), std::forward<Ts>(other_tensors)... } }; - std::vector<int> vs(seeds); - ARM_COMPUTE_ERROR_ON(vs.size() != tensors.size()); - int k = 0; - for(auto tp : tensors) - { - library->fill(*tp, std::forward<D>(dist), vs[k++]); - } -} +}; + +template <> +struct is_floating_point<half_float::half> : public std::true_type +{ +}; /** Helper function to get the testing range for each activation layer. * * @param[in] activation Activation function to test. - * @param[in] fixed_point_position (Optional) Number of bits for the fractional part. Defaults to 1. + * @param[in] data_type Data type. + * @param[in] fixed_point_position Number of bits for the fractional part. Defaults to 1. * * @return A pair containing the lower upper testing bounds for a given function. */ template <typename T> -inline std::pair<T, T> get_activation_layer_test_bounds(ActivationLayerInfo::ActivationFunction activation, int fixed_point_position = 1) +std::pair<T, T> get_activation_layer_test_bounds(ActivationLayerInfo::ActivationFunction activation, DataType data_type, int fixed_point_position = 0) { - bool is_float = std::is_same<T, float>::value; - is_float = is_float || std::is_same<T, half_float::half>::value; - std::pair<T, T> bounds; - // Set initial values - if(is_float) - { - bounds = std::make_pair(-255.f, 255.f); - } - else + switch(data_type) { - bounds = std::make_pair(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max()); - } + case DataType::F16: + { + using namespace half_float::literal; - // Reduce testing ranges - switch(activation) - { - case ActivationLayerInfo::ActivationFunction::LOGISTIC: - case ActivationLayerInfo::ActivationFunction::SOFT_RELU: - // Reduce range as exponent overflows - if(is_float) + switch(activation) { - bounds.first = -40.f; - bounds.second = 40.f; - } - else - { - bounds.first = -(1 << (fixed_point_position)); - bounds.second = 1 << (fixed_point_position); + case ActivationLayerInfo::ActivationFunction::SQUARE: + case ActivationLayerInfo::ActivationFunction::LOGISTIC: + case ActivationLayerInfo::ActivationFunction::SOFT_RELU: + // Reduce range as exponent overflows + bounds = std::make_pair(-10._h, 10._h); + break; + case ActivationLayerInfo::ActivationFunction::SQRT: + // Reduce range as sqrt should take a non-negative number + bounds = std::make_pair(0._h, 255._h); + break; + default: + bounds = std::make_pair(-255._h, 255._h); + break; } break; - case ActivationLayerInfo::ActivationFunction::TANH: - // Reduce range as exponent overflows - if(!is_float) + } + case DataType::F32: + switch(activation) { - bounds.first = -(1 << (fixed_point_position)); - bounds.second = 1 << (fixed_point_position); + case ActivationLayerInfo::ActivationFunction::LOGISTIC: + case ActivationLayerInfo::ActivationFunction::SOFT_RELU: + // Reduce range as exponent overflows + bounds = std::make_pair(-40.f, 40.f); + break; + case ActivationLayerInfo::ActivationFunction::SQRT: + // Reduce range as sqrt should take a non-negative number + bounds = std::make_pair(0.f, 255.f); + break; + default: + bounds = std::make_pair(-255.f, 255.f); + break; } break; - case ActivationLayerInfo::ActivationFunction::SQRT: - // Reduce range as sqrt should take a non-negative number - bounds.first = (is_float) ? 0 : 1; - break; - default: - break; - } - return bounds; -} -/** Helper function to get the testing range for batch normalization layer. - * - * @param[in] fixed_point_position (Optional) Number of bits for the fractional part. Defaults to 1. - * - * @return A pair containing the lower upper testing bounds. - */ -template <typename T> -std::pair<T, T> get_batchnormalization_layer_test_bounds(int fixed_point_position = 1) -{ - bool is_float = std::is_floating_point<T>::value; - std::pair<T, T> bounds; - - // Set initial values - if(is_float) - { - bounds = std::make_pair(-1.f, 1.f); - } - else - { - bounds = std::make_pair(1, 1 << (fixed_point_position)); - } - - return bounds; -} - -/** Fill mask with the corresponding given pattern. - * - * @param[in,out] mask Mask to be filled according to pattern - * @param[in] cols Columns (width) of mask - * @param[in] rows Rows (height) of mask - * @param[in] pattern Pattern to fill the mask according to - */ -inline void fill_mask_from_pattern(uint8_t *mask, int cols, int rows, MatrixPattern pattern) -{ - unsigned int v = 0; - std::mt19937 gen(user_config.seed.get()); - std::bernoulli_distribution dist(0.5); - - for(int r = 0; r < rows; ++r) - { - for(int c = 0; c < cols; ++c, ++v) - { - uint8_t val = 0; - - switch(pattern) + case DataType::QS8: + case DataType::QS16: + switch(activation) { - case MatrixPattern::BOX: - val = 255; - break; - case MatrixPattern::CROSS: - val = ((r == (rows / 2)) || (c == (cols / 2))) ? 255 : 0; - break; - case MatrixPattern::DISK: - val = (((r - rows / 2.0f + 0.5f) * (r - rows / 2.0f + 0.5f)) / ((rows / 2.0f) * (rows / 2.0f)) + ((c - cols / 2.0f + 0.5f) * (c - cols / 2.0f + 0.5f)) / ((cols / 2.0f) * - (cols / 2.0f))) <= 1.0f ? 255 : 0; + case ActivationLayerInfo::ActivationFunction::LOGISTIC: + case ActivationLayerInfo::ActivationFunction::SOFT_RELU: + case ActivationLayerInfo::ActivationFunction::TANH: + // Reduce range as exponent overflows + bounds = std::make_pair(-(1 << fixed_point_position), 1 << fixed_point_position); break; - case MatrixPattern::OTHER: - val = (dist(gen) ? 0 : 255); + case ActivationLayerInfo::ActivationFunction::SQRT: + // Reduce range as sqrt should take a non-negative number + // Can't be zero either as inv_sqrt is used in NEON. + bounds = std::make_pair(1, std::numeric_limits<T>::max()); break; default: - return; + bounds = std::make_pair(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max()); + break; } - - mask[v] = val; - } + break; + default: + ARM_COMPUTE_ERROR("Unsupported data type"); } - if(pattern == MatrixPattern::OTHER) - { - std::uniform_int_distribution<uint8_t> distribution_u8(0, ((cols * rows) - 1)); - mask[distribution_u8(gen)] = 255; - } + return bounds; } /** Calculate output tensor shape give a vector of input tensor to concatenate @@ -204,69 +135,7 @@ inline void fill_mask_from_pattern(uint8_t *mask, int cols, int rows, MatrixPatt * * @return The shape of output concatenated tensor. */ -inline TensorShape calculate_depth_concatenate_shape(std::vector<TensorShape> input_shapes) -{ - TensorShape out_shape = input_shapes.at(0); - - unsigned int max_x = 0; - unsigned int max_y = 0; - unsigned int depth = 0; - - for(auto const &shape : input_shapes) - { - max_x = std::max<unsigned int>(shape.x(), max_x); - max_y = std::max<unsigned int>(shape.y(), max_y); - depth += shape.z(); - } - - out_shape.set(0, max_x); - out_shape.set(1, max_y); - out_shape.set(2, depth); - - return out_shape; -} - -/** Fill matrix random. - * - * @param[in,out] matrix Matrix - * @param[in] cols Columns (width) of matrix - * @param[in] rows Rows (height) of matrix - */ -template <std::size_t SIZE> -inline void fill_warp_matrix(std::array<float, SIZE> &matrix, int cols, int rows) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_real_distribution<float> dist(-1, 1); - - for(int v = 0, r = 0; r < rows; ++r) - { - for(int c = 0; c < cols; ++c, ++v) - { - matrix[v] = dist(gen); - } - } - if(SIZE == 9) - { - matrix[(cols * rows) - 1] = 1; - } -} - -/** Helper function to fill the Lut random by a ILutAccessor. - * - * @param[in,out] table Accessor at the Lut. - * - */ -template <typename T> -void fill_lookuptable(T &&table) -{ - std::mt19937 generator(user_config.seed.get()); - std::uniform_int_distribution<typename T::value_type> distribution(std::numeric_limits<typename T::value_type>::min(), std::numeric_limits<typename T::value_type>::max()); - - for(int i = std::numeric_limits<typename T::value_type>::min(); i <= std::numeric_limits<typename T::value_type>::max(); i++) - { - table[i] = distribution(generator); - } -} +TensorShape calculate_depth_concatenate_shape(const std::vector<TensorShape> &input_shapes); } // namespace validation } // namespace test } // namespace arm_compute diff --git a/tests/validation/NEON/AbsoluteDifference.cpp b/tests/validation/NEON/AbsoluteDifference.cpp deleted file mode 100644 index 1aee95e2d8..0000000000 --- a/tests/validation/NEON/AbsoluteDifference.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEAbsoluteDifference.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::validation; - -namespace -{ -/** Compute Neon absolute difference function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * - * @return Computed output tensor. - */ -Tensor compute_absolute_difference(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt_in0); - Tensor src2 = create_tensor<Tensor>(shape, dt_in1); - Tensor dst = create_tensor<Tensor>(shape, dt_out); - - // Create and configure function - NEAbsoluteDifference abs_d; - abs_d.configure(&src1, &src2, &dst); - - // Allocate tensors - src1.allocator()->allocate(); - src2.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src1.info()->is_resizable()); - BOOST_TEST(!src2.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src1), 0); - library->fill_tensor_uniform(Accessor(src2), 1); - - // Compute function - abs_d.run(); - - return dst; -} - -void validate_configuration(const Tensor &src1, const Tensor &src2, Tensor &dst, TensorShape shape) -{ - BOOST_TEST(src1.info()->is_resizable()); - BOOST_TEST(src2.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEAbsoluteDifference abs_d; - abs_d.configure(&src1, &src2, &dst); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src1.info()->valid_region(), valid_region); - validate(src2.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src1.info()->padding(), padding); - validate(src2.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(AbsoluteDifference) - -BOOST_AUTO_TEST_SUITE(U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()), - shape) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::U8); - Tensor src2 = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - validate_configuration(src1, src2, dst, shape); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), - shape) -{ - // Compute function - Tensor dst = compute_absolute_difference(shape, DataType::U8, DataType::U8, DataType::U8); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_absolute_difference(shape, DataType::U8, DataType::U8, DataType::U8); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes(), - shape) -{ - // Compute function - Tensor dst = compute_absolute_difference(shape, DataType::U8, DataType::U8, DataType::U8); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_absolute_difference(shape, DataType::U8, DataType::U8, DataType::U8); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, dt) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt); - Tensor src2 = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - validate_configuration(src1, src2, dst, shape); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, dt) -{ - // Compute function - Tensor dst = compute_absolute_difference(shape, dt, DataType::S16, DataType::S16); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_absolute_difference(shape, dt, DataType::S16, DataType::S16); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, dt) -{ - // Compute function - Tensor dst = compute_absolute_difference(shape, dt, DataType::S16, DataType::S16); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_absolute_difference(shape, dt, DataType::S16, DataType::S16); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Accumulate.cpp b/tests/validation/NEON/Accumulate.cpp deleted file mode 100644 index 7e8a85065e..0000000000 --- a/tests/validation/NEON/Accumulate.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEAccumulate.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::validation; - -namespace -{ -/** Compute Neon accumulate function. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_accumulate(const TensorShape &shape) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - // Create and configure function - NEAccumulate acc; - acc.configure(&src, &dst); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - library->fill_tensor_uniform(Accessor(dst), 1); - - // Compute function - acc.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Accumulate) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()), - shape) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEAccumulate acc; - acc.configure(&src, &dst); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), - shape) -{ - // Compute function - Tensor dst = compute_accumulate(shape); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_accumulate(shape); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes(), - shape) -{ - // Compute function - Tensor dst = compute_accumulate(shape); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_accumulate(shape); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/AccumulateSquared.cpp b/tests/validation/NEON/AccumulateSquared.cpp deleted file mode 100644 index 83908425be..0000000000 --- a/tests/validation/NEON/AccumulateSquared.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEAccumulate.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::validation; - -namespace -{ -/** Compute Neon accumulate squared function. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_accumulate_squared(const TensorShape &shape, uint32_t shift) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - // Create and configure function - NEAccumulateSquared acc; - acc.configure(&src, shift, &dst); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - // dst tensor filled with non-negative values - library->fill_tensor_uniform(Accessor(src), 0); - library->fill_tensor_uniform(Accessor(dst), 1, static_cast<int16_t>(0), std::numeric_limits<int16_t>::max()); - - // Compute function - acc.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(AccumulateSquared) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::xrange(0U, 16U), - shape, shift) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEAccumulateSquared acc; - acc.configure(&src, shift, &dst); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::xrange(0U, 16U), - shape, shift) -{ - // Compute function - Tensor dst = compute_accumulate_squared(shape, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_accumulate_squared(shape, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ 0U, 1U, 15U }), - shape, shift) -{ - // Compute function - Tensor dst = compute_accumulate_squared(shape, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_accumulate_squared(shape, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/AccumulateWeighted.cpp b/tests/validation/NEON/AccumulateWeighted.cpp deleted file mode 100644 index ea71959c0b..0000000000 --- a/tests/validation/NEON/AccumulateWeighted.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEAccumulate.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::validation; - -namespace -{ -/** Compute Neon accumulate weighted function. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_accumulate_weighted(const TensorShape &shape, float alpha) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - // Create and configure function - NEAccumulateWeighted acc; - acc.configure(&src, alpha, &dst); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - library->fill_tensor_uniform(Accessor(dst), 1); - - // Compute function - acc.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(AccumulateWeighted) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ 0.f, 0.5f, 1.f }), - shape, alpha) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEAccumulateWeighted acc; - acc.configure(&src, alpha, &dst); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ 0.f, 0.5f, 1.f }), - shape, alpha) -{ - // Compute function - Tensor dst = compute_accumulate_weighted(shape, alpha); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_accumulate_weighted(shape, alpha); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ 0.f, 0.5f, 1.f }), - shape, alpha) -{ - // Compute function - Tensor dst = compute_accumulate_weighted(shape, alpha); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_accumulate_weighted(shape, alpha); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/ActivationLayer.cpp b/tests/validation/NEON/ActivationLayer.cpp new file mode 100644 index 0000000000..1c6811fd1c --- /dev/null +++ b/tests/validation/NEON/ActivationLayer.cpp @@ -0,0 +1,230 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEActivationLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ActivationFunctionsDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ActivationLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Define tolerance of the activation layer. + * + * @param[in] data_type The data type used. + * @param[in] activation The activation function used. + * + * @return Tolerance depending on the activation function. + */ +AbsoluteTolerance<float> tolerance(DataType data_type, ActivationLayerInfo::ActivationFunction activation) +{ + switch(activation) + { + case ActivationLayerInfo::ActivationFunction::LOGISTIC: + case ActivationLayerInfo::ActivationFunction::SOFT_RELU: + case ActivationLayerInfo::ActivationFunction::SQRT: + case ActivationLayerInfo::ActivationFunction::TANH: + switch(data_type) + { + case DataType::QS8: + return AbsoluteTolerance<float>(5.f); + case DataType::QS16: + return AbsoluteTolerance<float>(11.f); + case DataType::F16: + return AbsoluteTolerance<float>(0.01f); + default: + return AbsoluteTolerance<float>(0.00001f); + } + break; + default: + return AbsoluteTolerance<float>(0.f); + } +} + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ +#ifdef ARM_COMPUTE_ENABLE_FP16 + DataType::F16, +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + DataType::F32, + DataType::QS8, + DataType::QS16, +}); + +/** Input data sets. */ +const auto ActivationDataset = combine(combine(framework::dataset::make("InPlace", { false, true }), datasets::ActivationFunctions()), framework::dataset::make("AlphaBeta", { 0.5f, 1.f })); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(ActivationLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), CNNDataTypes), framework::dataset::make("InPlace", { false, true })), + shape, data_type, in_place) +{ + // Set fixed point position data type allowed + const int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + // Create tensors + Tensor src = create_tensor<Tensor>(shape, data_type, 1, fixed_point_position); + Tensor dst = create_tensor<Tensor>(shape, data_type, 1, fixed_point_position); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NEActivationLayer act_layer; + + if(in_place) + { + act_layer.configure(&src, nullptr, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::ABS)); + } + else + { + act_layer.configure(&src, &dst, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::ABS)); + } + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + + if(!in_place) + { + validate(dst.info()->valid_region(), valid_region); + } + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src.info()->padding(), padding); + + if(!in_place) + { + validate(dst.info()->padding(), padding); + } +} + +template <typename T> +using NEActivationLayerFixture = ActivationValidationFixture<Tensor, Accessor, NEActivationLayer, T>; + +TEST_SUITE(Float) +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEActivationLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance(_data_type, _function)); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEActivationLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance(_data_type, _function)); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEActivationLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), ActivationDataset), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance(_data_type, _function)); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEActivationLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), ActivationDataset), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance(_data_type, _function)); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using NEActivationLayerFixedPointFixture = ActivationValidationFixedPointFixture<Tensor, Accessor, NEActivationLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// We test for fixed point precision [3,5] because [1,2] and [6,7] ranges cause +// overflowing issues in most of the transcendentals functions. +FIXTURE_DATA_TEST_CASE(RunSmall, NEActivationLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 3, 6))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance(_data_type, _function)); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEActivationLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 3, 6))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance(_data_type, _function)); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14 +FIXTURE_DATA_TEST_CASE(RunSmall, NEActivationLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance(_data_type, _function)); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEActivationLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), ActivationDataset), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance(_data_type, _function)); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/ArithmeticAddition.cpp b/tests/validation/NEON/ArithmeticAddition.cpp deleted file mode 100644 index 952dcd207b..0000000000 --- a/tests/validation/NEON/ArithmeticAddition.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEArithmeticAddition.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::validation; - -namespace -{ -/** Compute Neon arithmetic addition function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Overflow policy of the operation. - * @param[in] fixed_point_position (Optional) Fixed point position that expresses the number of bits for the fractional part of the number when the tensor's data type is QS8 or QS16 (default = 0). - * - * @return Computed output tensor. - */ -Tensor compute_arithmetic_addition(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy policy, int fixed_point_position = 0) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt_in0, 1, fixed_point_position); - Tensor src2 = create_tensor<Tensor>(shape, dt_in1, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, dt_out, 1, fixed_point_position); - - // Create and configure function - NEArithmeticAddition add; - add.configure(&src1, &src2, &dst, policy); - - // Allocate tensors - src1.allocator()->allocate(); - src2.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src1.info()->is_resizable()); - BOOST_TEST(!src2.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src1), 0); - library->fill_tensor_uniform(Accessor(src2), 1); - - // Compute function - add.run(); - - return dst; -} - -void validate_configuration(const Tensor &src1, const Tensor &src2, Tensor &dst, TensorShape shape, ConvertPolicy policy) -{ - BOOST_TEST(src1.info()->is_resizable()); - BOOST_TEST(src2.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEArithmeticAddition add; - add.configure(&src1, &src2, &dst, policy); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src1.info()->valid_region(), valid_region); - validate(src2.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src1.info()->padding(), padding); - validate(src2.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(ArithmeticAddition) - -BOOST_AUTO_TEST_SUITE(U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::U8); - Tensor src2 = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, DataType::U8, DataType::U8, DataType::U8, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::U8, DataType::U8, DataType::U8, policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt); - Tensor src2 = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, dt, DataType::S16, DataType::S16, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, dt, DataType::S16, DataType::S16, policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, dt, DataType::S16, DataType::S16, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, dt, DataType::S16, DataType::S16, policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Quantized) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 7), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 7), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 15), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 15), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -#ifdef ARM_COMPUTE_ENABLE_FP16 -BOOST_AUTO_TEST_SUITE(F16) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, DataType::F16, DataType::F16, DataType::F16, ConvertPolicy::WRAP); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::F16, DataType::F16, DataType::F16, ConvertPolicy::WRAP); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -#endif /* ARM_COMPUTE_ENABLE_FP16 */ - -BOOST_AUTO_TEST_SUITE(F32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::F32); - Tensor src2 = create_tensor<Tensor>(shape, DataType::F32); - Tensor dst = create_tensor<Tensor>(shape, DataType::F32); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, DataType::F32, DataType::F32, DataType::F32, ConvertPolicy::WRAP); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::F32, DataType::F32, DataType::F32, ConvertPolicy::WRAP); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Compute function - Tensor dst = compute_arithmetic_addition(shape, DataType::F32, DataType::F32, DataType::F32, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_addition(shape, DataType::F32, DataType::F32, DataType::F32, policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/ArithmeticSubtraction.cpp b/tests/validation/NEON/ArithmeticSubtraction.cpp deleted file mode 100644 index b95bc05d75..0000000000 --- a/tests/validation/NEON/ArithmeticSubtraction.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEArithmeticSubtraction.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::validation; - -namespace -{ -/** Compute Neon arithmetic subtraction function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Overflow policy of the operation. - * @param[in] fixed_point_position (Optional) Fixed point position that expresses the number of bits for the fractional part of the number when the tensor's data type is QS8 or QS16 (default = 0). - * - * @return Computed output tensor. - */ -Tensor compute_arithmetic_subtraction(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy policy, int fixed_point_position = 0) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt_in0, 1, fixed_point_position); - Tensor src2 = create_tensor<Tensor>(shape, dt_in1, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, dt_out, 1, fixed_point_position); - - // Create and configure function - NEArithmeticSubtraction sub; - sub.configure(&src1, &src2, &dst, policy); - - // Allocate tensors - src1.allocator()->allocate(); - src2.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src1.info()->is_resizable()); - BOOST_TEST(!src2.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src1), 0); - library->fill_tensor_uniform(Accessor(src2), 1); - - // Compute function - sub.run(); - - return dst; -} - -void validate_configuration(const Tensor &src1, const Tensor &src2, Tensor &dst, TensorShape shape, ConvertPolicy policy) -{ - BOOST_TEST(src1.info()->is_resizable()); - BOOST_TEST(src2.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEArithmeticSubtraction sub; - sub.configure(&src1, &src2, &dst, policy); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src1.info()->valid_region(), valid_region); - validate(src2.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src1.info()->padding(), padding); - validate(src2.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(ArithmeticSubtraction) - -BOOST_AUTO_TEST_SUITE(U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::U8); - Tensor src2 = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, DataType::U8, DataType::U8, DataType::U8, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::U8, DataType::U8, DataType::U8, policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt); - Tensor src2 = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, dt, DataType::S16, DataType::S16, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, dt, DataType::S16, DataType::S16, policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, dt, policy) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, dt, DataType::S16, DataType::S16, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, dt, DataType::S16, DataType::S16, policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Quantized) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 7), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 7), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::QS8, DataType::QS8, DataType::QS8, policy, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 15), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * ConvertPolicies() * boost::unit_test::data::xrange(1, 15), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::QS16, DataType::QS16, DataType::QS16, policy, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -#ifdef ARM_COMPUTE_ENABLE_FP16 -BOOST_AUTO_TEST_SUITE(Float16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, DataType::F16, DataType::F16, DataType::F16, ConvertPolicy::WRAP); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::F16, DataType::F16, DataType::F16, ConvertPolicy::WRAP); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -#endif /* ARM_COMPUTE_ENABLE_FP16 */ - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::F32); - Tensor src2 = create_tensor<Tensor>(shape, DataType::F32); - Tensor dst = create_tensor<Tensor>(shape, DataType::F32); - - validate_configuration(src1, src2, dst, shape, policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, DataType::F32, DataType::F32, DataType::F32, ConvertPolicy::WRAP); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::F32, DataType::F32, DataType::F32, ConvertPolicy::WRAP); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }), - shape, policy) -{ - // Compute function - Tensor dst = compute_arithmetic_subtraction(shape, DataType::F32, DataType::F32, DataType::F32, policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_arithmetic_subtraction(shape, DataType::F32, DataType::F32, DataType::F32, policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/BatchNormalizationLayer.cpp b/tests/validation/NEON/BatchNormalizationLayer.cpp deleted file mode 100644 index 9898beb7db..0000000000 --- a/tests/validation/NEON/BatchNormalizationLayer.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - * 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 "NEON/Accessor.h" -#include "TypePrinter.h" -#include "dataset/BatchNormalizationLayerDataset.h" -#include "tests/Globals.h" -#include "tests/NEON/Helper.h" -#include "tests/Utils.h" -#include "tests/validation/Helpers.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" - -#include "arm_compute/runtime/NEON/functions/NEBatchNormalizationLayer.h" - -#include <random> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -const float tolerance_qs8 = 6; /**< Tolerance value for comparing reference's output against quantized implementation's output */ -const float tolerance_qs16 = 6; /**< Tolerance value for comparing reference's output against quantized implementation's output */ -const float tolerance_f32 = 1e-05f; /**< Tolerance value for comparing reference's output against floating point implementation's output */ -#ifdef ARM_COMPUTE_ENABLE_FP16 -const float tolerance_f16 = 0.01f; /**< Tolerance value for comparing reference's output against half precision floating point implementation's output */ -#endif /* ARM_COMPUTE_ENABLE_FP16 */ - -/** Compute Neon batch normalization function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt Data type of input and output tensors. - * @param[in] norm_info Normalization Layer information. - * - * @return Computed output tensor. - */ -Tensor compute_reference_batch_normalization_layer(const TensorShape &shape0, const TensorShape &shape1, DataType dt, float epsilon, int fixed_point_position = 0) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape0, dt, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape0, dt, 1, fixed_point_position); - Tensor mean = create_tensor<Tensor>(shape1, dt, 1, fixed_point_position); - Tensor var = create_tensor<Tensor>(shape1, dt, 1, fixed_point_position); - Tensor beta = create_tensor<Tensor>(shape1, dt, 1, fixed_point_position); - Tensor gamma = create_tensor<Tensor>(shape1, dt, 1, fixed_point_position); - - // Create and configure function - NEBatchNormalizationLayer norm; - norm.configure(&src, &dst, &mean, &var, &beta, &gamma, epsilon); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - mean.allocator()->allocate(); - var.allocator()->allocate(); - beta.allocator()->allocate(); - gamma.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - BOOST_TEST(!mean.info()->is_resizable()); - BOOST_TEST(!var.info()->is_resizable()); - BOOST_TEST(!beta.info()->is_resizable()); - BOOST_TEST(!gamma.info()->is_resizable()); - - // Fill tensors - switch(dt) - { - case DataType::QS8: - { - const std::pair<int8_t, int8_t> bounds = get_batchnormalization_layer_test_bounds<int8_t>(fixed_point_position); - std::uniform_int_distribution<> distribution(bounds.first, bounds.second); - std::uniform_int_distribution<> distribution_var(0, bounds.second); - test::fill_tensors(distribution, { 0, 1, 3, 4 }, &src, &mean, &beta, &gamma); - test::fill_tensors(distribution_var, { 0 }, &var); - break; - } - case DataType::QS16: - { - const std::pair<int16_t, int16_t> bounds = get_batchnormalization_layer_test_bounds<int16_t>(fixed_point_position); - std::uniform_int_distribution<> distribution(bounds.first, bounds.second); - std::uniform_int_distribution<> distribution_var(0, bounds.second); - test::fill_tensors(distribution, { 0, 1, 3, 4 }, &src, &mean, &beta, &gamma); - test::fill_tensors(distribution_var, { 0 }, &var); - break; - } -#ifdef ARM_COMPUTE_ENABLE_FP16 - case DataType::F16: - { - const std::pair<half_float::half, half_float::half> bounds = get_batchnormalization_layer_test_bounds<half_float::half>(); - std::uniform_real_distribution<> distribution(bounds.first, bounds.second); - std::uniform_real_distribution<> distribution_var(0, bounds.second); - test::fill_tensors(distribution, { 0, 1, 3, 4 }, &src, &mean, &beta, &gamma); - test::fill_tensors(distribution_var, { 0 }, &var); - break; - } -#endif /* ARM_COMPUTE_ENABLE_FP16 */ - case DataType::F32: - { - const std::pair<float, float> bounds = get_batchnormalization_layer_test_bounds<float>(); - std::uniform_real_distribution<> distribution(bounds.first, bounds.second); - std::uniform_real_distribution<> distribution_var(0, bounds.second); - test::fill_tensors(distribution, { 0, 1, 3, 4 }, &src, &mean, &beta, &gamma); - test::fill_tensors(distribution_var, { 0 }, &var); - break; - } - default: - { - ARM_COMPUTE_ERROR("Not supported"); - break; - } - } - - // Compute function - norm.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(BatchNormalizationLayer) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make({ DataType::QS8, DataType::QS16, DataType::F32 }), obj, dt) -{ - // Set fixed point position data type allowed - int fixed_point_position = (arm_compute::is_data_type_fixed_point(dt)) ? 3 : 0; - - // Create tensors - Tensor src = create_tensor<Tensor>(obj.shape0, dt, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(obj.shape0, dt, 1, fixed_point_position); - Tensor mean = create_tensor<Tensor>(obj.shape1, dt, 1, fixed_point_position); - Tensor var = create_tensor<Tensor>(obj.shape1, dt, 1, fixed_point_position); - Tensor beta = create_tensor<Tensor>(obj.shape1, dt, 1, fixed_point_position); - Tensor gamma = create_tensor<Tensor>(obj.shape1, dt, 1, fixed_point_position); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - BOOST_TEST(mean.info()->is_resizable()); - BOOST_TEST(var.info()->is_resizable()); - BOOST_TEST(beta.info()->is_resizable()); - BOOST_TEST(gamma.info()->is_resizable()); - - // Create and configure function - NEBatchNormalizationLayer norm; - norm.configure(&src, &dst, &mean, &var, &beta, &gamma, obj.epsilon); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(obj.shape0); - const ValidRegion valid_region_vec = shape_to_valid_region(obj.shape1); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - validate(mean.info()->valid_region(), valid_region_vec); - validate(var.info()->valid_region(), valid_region_vec); - validate(beta.info()->valid_region(), valid_region_vec); - validate(gamma.info()->valid_region(), valid_region_vec); -} - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(Random, - RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::F32), - obj, dt) -{ - // Compute function - Tensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance_f32, 0); -} -BOOST_AUTO_TEST_SUITE_END() - -#ifdef ARM_COMPUTE_ENABLE_FP16 -BOOST_AUTO_TEST_SUITE(Float16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(Random, - RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::F16), - obj, dt) -{ - // Compute function - Tensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance_f16, 0); -} -BOOST_AUTO_TEST_SUITE_END() -#endif /* ARM_COMPUTE_ENABLE_FP16 */ - -BOOST_AUTO_TEST_SUITE(Quantized) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(Random, - RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::QS8) * boost::unit_test::data::xrange(1, 6), - obj, dt, fixed_point_position) -{ - // Compute function - Tensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance_qs8); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(Random, - RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::QS16) * boost::unit_test::data::xrange(1, 14), - obj, dt, fixed_point_position) -{ - // Compute function - Tensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance_qs16); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/BitwiseAnd.cpp b/tests/validation/NEON/BitwiseAnd.cpp new file mode 100644 index 0000000000..179413ee39 --- /dev/null +++ b/tests/validation/NEON/BitwiseAnd.cpp @@ -0,0 +1,94 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEBitwiseAnd.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/BitwiseAndFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(BitwiseAnd) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + Tensor src1 = create_tensor<Tensor>(shape, data_type); + Tensor src2 = create_tensor<Tensor>(shape, data_type); + Tensor dst = create_tensor<Tensor>(shape, data_type); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NEBitwiseAnd bitwise_and; + bitwise_and.configure(&src1, &src2, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src1.info()->valid_region(), valid_region); + validate(src2.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src1.info()->padding(), padding); + validate(src2.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using NEBitwiseAndFixture = BitwiseAndValidationFixture<Tensor, Accessor, NEBitwiseAnd, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, NEBitwiseAndFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEBitwiseAndFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/BitwiseNot.cpp b/tests/validation/NEON/BitwiseNot.cpp new file mode 100644 index 0000000000..c438a5700b --- /dev/null +++ b/tests/validation/NEON/BitwiseNot.cpp @@ -0,0 +1,90 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEBitwiseNot.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/BitwiseNotFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(BitwiseNot) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + Tensor src = create_tensor<Tensor>(shape, data_type); + Tensor dst = create_tensor<Tensor>(shape, data_type); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NEBitwiseNot bitwise_not; + bitwise_not.configure(&src, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using NEBitwiseNotFixture = BitwiseNotValidationFixture<Tensor, Accessor, NEBitwiseNot, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, NEBitwiseNotFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEBitwiseNotFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/BitwiseOr.cpp b/tests/validation/NEON/BitwiseOr.cpp new file mode 100644 index 0000000000..0e4cdbe2c1 --- /dev/null +++ b/tests/validation/NEON/BitwiseOr.cpp @@ -0,0 +1,94 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEBitwiseOr.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/BitwiseOrFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(BitwiseOr) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + Tensor src1 = create_tensor<Tensor>(shape, data_type); + Tensor src2 = create_tensor<Tensor>(shape, data_type); + Tensor dst = create_tensor<Tensor>(shape, data_type); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NEBitwiseOr bitwise_or; + bitwise_or.configure(&src1, &src2, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src1.info()->valid_region(), valid_region); + validate(src2.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src1.info()->padding(), padding); + validate(src2.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using NEBitwiseOrFixture = BitwiseOrValidationFixture<Tensor, Accessor, NEBitwiseOr, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, NEBitwiseOrFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEBitwiseOrFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/BitwiseXor.cpp b/tests/validation/NEON/BitwiseXor.cpp new file mode 100644 index 0000000000..70363c041b --- /dev/null +++ b/tests/validation/NEON/BitwiseXor.cpp @@ -0,0 +1,94 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEBitwiseXor.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/BitwiseXorFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(BitwiseXor) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + Tensor src1 = create_tensor<Tensor>(shape, data_type); + Tensor src2 = create_tensor<Tensor>(shape, data_type); + Tensor dst = create_tensor<Tensor>(shape, data_type); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NEBitwiseXor bitwise_xor; + bitwise_xor.configure(&src1, &src2, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src1.info()->valid_region(), valid_region); + validate(src2.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src1.info()->padding(), padding); + validate(src2.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using NEBitwiseXorFixture = BitwiseXorValidationFixture<Tensor, Accessor, NEBitwiseXor, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, NEBitwiseXorFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEBitwiseXorFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/Box3x3.cpp b/tests/validation/NEON/Box3x3.cpp deleted file mode 100644 index 579b2c8af1..0000000000 --- a/tests/validation/NEON/Box3x3.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NEBox3x3.h" -#include "arm_compute/runtime/SubTensor.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::validation; - -namespace -{ -constexpr unsigned int filter_size = 3; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute Neon box3x3 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor. - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT. - * - * @return Computed output tensor. - */ -Tensor compute_box3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - // Create and configure function - NEBox3x3 box3x3; - box3x3.configure(&src, &dst, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - box3x3.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Box3x3) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEBox3x3 box3x3; - box3x3.configure(&src, &dst, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - validate(src.info()->valid_region(), src_valid_region); - validate(dst.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - calculator.set_border_size(1); - calculator.set_border_mode(border_mode); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-1); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - Tensor dst = compute_box3x3(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_box3x3(shape, border_mode, border_value); - - // Validate output - validate(Accessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - Tensor dst = compute_box3x3(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_box3x3(shape, border_mode, border_value); - - // Validate output - validate(Accessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/CMakeLists.txt b/tests/validation/NEON/CMakeLists.txt deleted file mode 100644 index bf07d27d6a..0000000000 --- a/tests/validation/NEON/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -# 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. -cmake_minimum_required (VERSION 3.1) - -set(arm_compute_test_validation_NEON_SOURCE_FILES - ${CMAKE_SOURCE_DIR}/NEON/Helper.h - ${CMAKE_SOURCE_DIR}/NEON/Accessor.h - ${CMAKE_CURRENT_SOURCE_DIR}/AbsoluteDifference.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Accumulate.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/AccumulateSquared.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/AccumulateWeighted.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ArithmeticAddition.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ArithmeticSubtraction.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/BatchNormalizationLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/BitwiseAnd.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/BitwiseNot.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/BitwiseOr.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/BitwiseXor.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Box3x3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ConvolutionLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/DirectConvolutionLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/DepthConvert.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/FillBorder.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Fixedpoint/Exp_QS8.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Fixedpoint/Invsqrt_QS8.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Fixedpoint/Log_QS8.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Fixedpoint/Reciprocal_QS8.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/FullyConnectedLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Gaussian3x3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/GEMM.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/HarrisCorners.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/IntegralImage.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/NormalizationLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/PixelWiseMultiplication.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/MeanStdDev.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Pooling/PoolingLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Sobel3x3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Sobel5x5.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/SoftmaxLayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Threshold.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/MinMaxLocation.cpp -) - -add_library(arm_compute_test_validation_NEON OBJECT - ${arm_compute_test_validation_NEON_SOURCE_FILES} -) - -set(arm_compute_test_validation_TARGET_OBJECTS - ${arm_compute_test_validation_TARGET_OBJECTS} - $<TARGET_OBJECTS:arm_compute_test_validation_NEON> - PARENT_SCOPE -) diff --git a/tests/validation/NEON/ConvolutionLayer.cpp b/tests/validation/NEON/ConvolutionLayer.cpp new file mode 100644 index 0000000000..7a3306d232 --- /dev/null +++ b/tests/validation/NEON/ConvolutionLayer.cpp @@ -0,0 +1,192 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEConvolutionLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/LargeConvolutionLayerDataset.h" +#include "tests/datasets/SmallConvolutionLayerDataset.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ConvolutionLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +const AbsoluteTolerance<float> tolerance_f32(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F32 */ +#ifdef ARM_COMPUTE_ENABLE_FP16 +const AbsoluteTolerance<float> tolerance_f16(0.01f); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F16 */ +#endif /* ARM_COMPUTE_ENABLE_FP16 */ +const AbsoluteTolerance<float> tolerance_q(1.0f); /**< Tolerance value for comparing reference's output against implementation's output for fixed point data types */ + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ +#ifdef ARM_COMPUTE_ENABLE_FP16 + DataType::F16, +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + DataType::F32, + DataType::QS8, + DataType::QS16, +}); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(ConvolutionLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(framework::dataset::concat(datasets::SmallConvolutionLayerDataset(), datasets::LargeConvolutionLayerDataset()), CNNDataTypes), + input_shape, weights_shape, bias_shape, output_shape, info, data_type) +{ + // Set fixed point position data type allowed + int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + // Create tensors + Tensor src = create_tensor<Tensor>(input_shape, data_type, 1, fixed_point_position); + Tensor weights = create_tensor<Tensor>(weights_shape, data_type, 1, fixed_point_position); + Tensor bias = create_tensor<Tensor>(bias_shape, data_type, 1, fixed_point_position); + Tensor dst = create_tensor<Tensor>(output_shape, data_type, 1, fixed_point_position); + + 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 + NEConvolutionLayer conv; + conv.configure(&src, &weights, &bias, &dst, info); + + // 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? +} + +template <typename T> +using NEConvolutionLayerFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolutionLayer, T>; + +TEST_SUITE(Float) +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using NEConvolutionLayerFixedPointFixture = ConvolutionValidationFixedPointFixture<Tensor, Accessor, NEConvolutionLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// We test for fixed point precision [4,6] +FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 4, 7))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_q); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 4, 7))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_q); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) +FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_q); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_q); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/DepthConcatenateLayer.cpp b/tests/validation/NEON/DepthConcatenateLayer.cpp new file mode 100644 index 0000000000..19a41ee9d6 --- /dev/null +++ b/tests/validation/NEON/DepthConcatenateLayer.cpp @@ -0,0 +1,125 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEDepthConcatenate.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/DepthConcatenateLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(DepthConcatenateLayer) + +//TODO(COMPMID-415): Add configuration test? + +template <typename T> +using NEDepthConcatenateLayerFixture = DepthConcatenateValidationFixture<Tensor, Accessor, NEDepthConcatenate, T>; + +TEST_SUITE(Float) +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEDepthConcatenateLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEDepthConcatenateLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEDepthConcatenateLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEDepthConcatenateLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +FIXTURE_DATA_TEST_CASE(RunSmall, NEDepthConcatenateLayerFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), + framework::dataset::make("DataType", + DataType::QS8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEDepthConcatenateLayerFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), + framework::dataset::make("DataType", + DataType::QS8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEDepthConcatenateLayerFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), + framework::dataset::make("DataType", + DataType::QS16))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEDepthConcatenateLayerFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), + framework::dataset::make("DataType", + DataType::QS16))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/DepthConvert.cpp b/tests/validation/NEON/DepthConvert.cpp deleted file mode 100644 index 0b7a175f4f..0000000000 --- a/tests/validation/NEON/DepthConvert.cpp +++ /dev/null @@ -1,637 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEDepthConvert.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::validation; - -namespace -{ -/** Compute Neon depth convert function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in Data type of input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Conversion policy. - * @param[in] shift Value for down/up conversions. Must be 0 <= shift < 8. - * @param[in] fixed_point_position_in (Optional) Fixed point position for the input tensor. - * @param[in] fixed_point_position_out (Optional) Fixed point position for the output tensor. - * - * @return Computed output tensor. - */ -Tensor compute_depth_convert(const TensorShape &shape, DataType dt_in, DataType dt_out, ConvertPolicy policy, - uint32_t shift, uint32_t fixed_point_position_in = 0, uint32_t fixed_point_position_out = 0) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, dt_in, 1, fixed_point_position_in); - Tensor dst = create_tensor<Tensor>(shape, dt_out, 1, fixed_point_position_out); - - // Create and configure function - NEDepthConvert depth_convert; - depth_convert.configure(&src, &dst, policy, shift); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - depth_convert.run(); - - return dst; -} -/** Configure and validate region/padding function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in Data type of input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Conversion policy. - * @param[in] shift Value for down/up conversions. Must be 0 <= shift < 8. - * @param[in] fixed_point_position_in (Optional) Fixed point position for the input tensor. - * @param[in] fixed_point_position_out (Optional) Fixed point position for the output tensor. - * - */ - -void compute_configure_validate(const TensorShape &shape, DataType dt_in, DataType dt_out, ConvertPolicy policy, - uint32_t shift, uint32_t fixed_point_position_in = 0, uint32_t fixed_point_position_out = 0) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, dt_in, 1, fixed_point_position_in); - Tensor dst = create_tensor<Tensor>(shape, dt_out, 1, fixed_point_position_out); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEDepthConvert depth_convert; - depth_convert.configure(&src, &dst, policy, shift); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(DepthConvert) - -BOOST_AUTO_TEST_SUITE(QS8_to_QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * (boost::unit_test::data::make({ 1, 3, 5, 6 }) ^ boost::unit_test::data::make({ 6, 5, 1, 3 })), - shape, policy, fixed_point_position_in, fixed_point_position_out) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::QS8, DataType::QS8, policy, 0, fixed_point_position_in, fixed_point_position_out); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * (boost::unit_test::data::make({ 1, 3, 5, 6 }) ^ boost::unit_test::data::make({ 6, 5, 1, 3 })), - shape, policy, fixed_point_position_in, fixed_point_position_out) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::QS8, DataType::QS8, policy, 0, fixed_point_position_in, fixed_point_position_out); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::QS8, DataType::QS8, policy, 0, fixed_point_position_in, fixed_point_position_out); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS8_to_F32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 7, 1), - shape, policy, fixed_point_position) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::QS8, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 7, 1), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::QS8, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::QS8, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 7, 1), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::QS8, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::QS8, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(F32_to_QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 7, 1), - shape, policy, fixed_point_position) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::F32, DataType::QS8, policy, 0, fixed_point_position, fixed_point_position); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 7, 1), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::F32, DataType::QS8, policy, 0, fixed_point_position, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::F32, DataType::QS8, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 7, 1), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::F32, DataType::QS8, policy, 0, fixed_point_position, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::F32, DataType::QS8, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16_to_QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * (boost::unit_test::data::make({ 3, 6, 7, 13, 14 }) ^ boost::unit_test::data::make({ 5, 10, 14, 4, 7 })), - shape, policy, fixed_point_position_in, fixed_point_position_out) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::QS16, DataType::QS16, policy, 0, fixed_point_position_in, fixed_point_position_out); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * (boost::unit_test::data::make({ 3, 6, 7, 13, 14 }) ^ boost::unit_test::data::make({ 5, 10, 14, 4, 7 })), - shape, policy, fixed_point_position_in, fixed_point_position_out) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::QS16, DataType::QS16, policy, 0, fixed_point_position_in, fixed_point_position_out); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::QS16, DataType::QS16, policy, 0, fixed_point_position_in, fixed_point_position_out); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16_to_F32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 15, 1), - shape, policy, fixed_point_position) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::QS16, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 15, 1), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::QS16, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::QS16, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 15, 1), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::QS16, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::QS16, DataType::F32, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(F32_to_QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 7, 1), - shape, policy, fixed_point_position) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::F32, DataType::QS16, policy, 0, fixed_point_position, fixed_point_position); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 15, 1), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::F32, DataType::QS16, policy, 0, fixed_point_position, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::F32, DataType::QS16, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE }) - * boost::unit_test::data::xrange(1, 15, 1), - shape, policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::F32, DataType::QS16, policy, 0, fixed_point_position, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::F32, DataType::QS16, policy, 0, fixed_point_position, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U8_to_U16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) - -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U8, DataType::U16, policy, shift, 0); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U8, DataType::U16, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::U16, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U8, DataType::U16, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::U16, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U8_to_S16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U8, DataType::S16, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U8, DataType::S16, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::S16, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U8, DataType::S16, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::S16, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U8_to_S32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U8, DataType::S32, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U8, DataType::S32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::S32, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U8, DataType::S32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U8, DataType::S32, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U16_to_U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U16, DataType::U8, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U16, DataType::U8, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U16, DataType::U8, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U16, DataType::U8, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U16, DataType::U8, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(U16_to_U32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::U16, DataType::U32, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U16, DataType::U32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U16, DataType::U32, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::U16, DataType::U32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::U16, DataType::U32, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16_to_U8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::S16, DataType::U8, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::S16, DataType::U8, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::S16, DataType::U8, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::S16, DataType::U8, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::S16, DataType::U8, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16_to_S32) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute configure and validate region/padding - compute_configure_validate(shape, DataType::S16, DataType::S32, policy, shift); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::S16, DataType::S32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::S16, DataType::S32, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ ConvertPolicy::SATURATE, ConvertPolicy::WRAP }) - * boost::unit_test::data::xrange(0, 7, 1), - shape, policy, shift) -{ - // Compute function - Tensor dst = compute_depth_convert(shape, DataType::S16, DataType::S32, policy, shift); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_depth_convert(shape, DataType::S16, DataType::S32, policy, shift); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/DequantizationLayer.cpp b/tests/validation/NEON/DequantizationLayer.cpp new file mode 100644 index 0000000000..22d56ab5d8 --- /dev/null +++ b/tests/validation/NEON/DequantizationLayer.cpp @@ -0,0 +1,100 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEDequantizationLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/DequantizationLayerFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(DequantizationLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + Tensor src = create_tensor<Tensor>(shape, data_type); + Tensor dst = create_tensor<Tensor>(shape, DataType::F32); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + float min = 0.f; + float max = 0.f; + NEDequantizationLayer dequant_layer; + dequant_layer.configure(&src, &dst, &min, &max); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 8).required_padding(); + validate(src.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using NEDequantizationLayerFixture = DequantizationValidationFixture<Tensor, Accessor, NEDequantizationLayer, T>; + +TEST_SUITE(Integer) +TEST_SUITE(U8) +FIXTURE_DATA_TEST_CASE(RunSmall, NEDequantizationLayerFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), framework::dataset::make("DataType", DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEDequantizationLayerFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), framework::dataset::make("DataType", DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/DirectConvolutionLayer.cpp b/tests/validation/NEON/DirectConvolutionLayer.cpp new file mode 100644 index 0000000000..6211d31c45 --- /dev/null +++ b/tests/validation/NEON/DirectConvolutionLayer.cpp @@ -0,0 +1,149 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEDirectConvolutionLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/DirectConvolutionLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr AbsoluteTolerance<float> tolerance_qs(1.f); /**< Tolerance for fixed point tests */ +#ifdef ARM_COMPUTE_ENABLE_FP16 +constexpr AbsoluteTolerance<float> tolerance_fp16(0.01f); /**< Tolerance for half precision floating point tests */ +#endif /* ARM_COMPUTE_ENABLE_FP16 */ +constexpr AbsoluteTolerance<float> tolerance_fp32(0.001f); /**< Tolerance for floating point tests */ + +/** Direct convolution data set. */ +const auto data_pad_f32 = concat(concat(combine(framework::dataset::make("PadX", 0), + combine(framework::dataset::make("PadY", 0), + framework::dataset::make("KernelSize", 1))), + combine(framework::dataset::make("PadX", 0, 2), + combine(framework::dataset::make("PadY", 0, 2), + framework::dataset::make("KernelSize", 3)))), + combine(framework::dataset::make("PadX", 0, 3), + combine(framework::dataset::make("PadY", 0, 3), + framework::dataset::make("KernelSize", 5)))); + +const auto data_pad_qs8 = concat(combine(framework::dataset::make("PadX", 0), + combine(framework::dataset::make("PadY", 0), + framework::dataset::make("KernelSize", 1))), + combine(framework::dataset::make("PadX", 0, 2), + combine(framework::dataset::make("PadY", 0, 2), + framework::dataset::make("KernelSize", 3)))); + +const auto data_f32 = combine(datasets::SmallDirectConvolutionShapes(), + combine(framework::dataset::make("StrideX", 1, 3), + combine(framework::dataset::make("StrideY", 1, 3), + combine(data_pad_f32, + framework::dataset::make("NumKernels", { 1, 4, 8, 16 }))))); + +const auto data_qs8 = combine(datasets::SmallDirectConvolutionShapes(), + combine(framework::dataset::make("StrideX", 1, 3), + combine(framework::dataset::make("StrideY", 1, 3), + combine(data_pad_qs8, + framework::dataset::make("NumKernels", { 1, 4, 8, 16 }))))); + +/** Direct convolution QS16 data set. */ +const auto data_qs16 = combine(datasets::SmallDirectConvolutionShapes(), + combine(framework::dataset::make("StrideX", 1, 3), + combine(framework::dataset::make("StrideY", 1, 3), + combine(framework::dataset::make("PadX", 0), + combine(framework::dataset::make("PadY", 0), + combine(framework::dataset::make("KernelSize", 1), + framework::dataset::make("NumKernels", { 1, 4, 8, 16 }))))))); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(DirectConvolutionLayer) + +//TODO(COMPMID-415): Configuration tests? + +template <typename T> +using NEDirectConvolutionLayerFixture = DirectConvolutionValidationFixture<Tensor, Accessor, NEDirectConvolutionLayer, T>; + +TEST_SUITE(Float) +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(Run, NEDirectConvolutionLayerFixture<half_float::half>, framework::DatasetMode::ALL, combine(data_f32, framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fp16); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(Run, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::ALL, combine(data_f32, framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fp32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using NEDirectConvolutionLayerFixedPointFixture = DirectConvolutionValidationFixedPointFixture<Tensor, Accessor, NEDirectConvolutionLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// We test for fixed point precision [4,6] +FIXTURE_DATA_TEST_CASE(Run, NEDirectConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(data_qs8, framework::dataset::make("DataType", DataType::QS8)), + framework::dataset::make("FractionalBits", 4, 7))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// We test for fixed point precision [4,13] +FIXTURE_DATA_TEST_CASE(Run, NEDirectConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::ALL, combine(combine(data_qs16, framework::dataset::make("DataType", DataType::QS16)), + framework::dataset::make("FractionalBits", 4, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/FillBorder.cpp b/tests/validation/NEON/FillBorder.cpp deleted file mode 100644 index ef2c1ff6f8..0000000000 --- a/tests/validation/NEON/FillBorder.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/kernels/NEFillBorderKernel.h" -#include "arm_compute/core/Types.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::validation; - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(FillBorder, BorderModes() * boost::unit_test::data::make({ PaddingSize{ 0 }, PaddingSize{ 1, 0, 1, 2 }, PaddingSize{ 10 } }), border_mode, padding) -{ - constexpr uint8_t border_value = 42U; - constexpr uint8_t tensor_value = 89U; - BorderSize border_size{ 5 }; - - // Create tensors - Tensor src = create_tensor<Tensor>(TensorShape{ 10U, 10U, 2U }, DataType::U8); - - src.info()->extend_padding(padding); - - // Allocate tensor - src.allocator()->allocate(); - - // Check padding is as required - validate(src.info()->padding(), padding); - - // Fill tensor with constant value - std::uniform_int_distribution<uint8_t> distribution{ tensor_value, tensor_value }; - library->fill(Accessor(src), distribution, 0); - - // Create and configure kernel - NEFillBorderKernel fill_border; - fill_border.configure(&src, border_size, border_mode, border_value); - - // Run kernel - fill_border.run(fill_border.window()); - - // Validate border - border_size.limit(padding); - validate(Accessor(src), border_size, border_mode, &border_value); - - // Validate tensor - validate(Accessor(src), &tensor_value); -} - -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Fixedpoint/Exp_QS16.cpp b/tests/validation/NEON/Fixedpoint/Exp_QS16.cpp deleted file mode 100644 index dc8603c963..0000000000 --- a/tests/validation/NEON/Fixedpoint/Exp_QS16.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/ReferenceCPP.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/NEFixedPoint.h" -#include "arm_compute/core/Types.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::validation; - -namespace -{ -const float tolerance = 1.0f; /**< Tolerance value for comparing reference's output against implementation's output */ - -/** Compute Neon exponential function for signed 16 bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_exp_qs16(const TensorShape &shape, int fixed_point_position) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::QS16, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, DataType::QS16, 1, fixed_point_position); - - constexpr unsigned int num_elems_processed_per_iteration = 8; - Window window = calculate_max_window(*src.info(), Steps(num_elems_processed_per_iteration)); - AccessWindowHorizontal input_access(src.info(), 0, num_elems_processed_per_iteration); - AccessWindowHorizontal output_access(dst.info(), 0, num_elems_processed_per_iteration); - - update_window_and_padding(window, input_access, output_access); - output_access.set_valid_region(window, src.info()->valid_region()); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors. Keep the range between [-1.0, 1.0) so the result won't - // overflow. - std::uniform_int_distribution<> distribution(-(1 << (fixed_point_position - 1)), (1 << (fixed_point_position - 1))); - library->fill(Accessor(src), distribution, 0); - - Iterator input(&src, window); - Iterator output(&dst, window); - - execute_window_loop(window, [&](const Coordinates & id) - { - qint16x8_t in = vld1q_qs16(reinterpret_cast<const qint16_t *>(input.ptr())); - // Use saturated exp - vst1q_qs16(reinterpret_cast<qint16_t *>(output.ptr()), vqexpq_qs16(in, fixed_point_position)); - }, - input, output); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_AUTO_TEST_SUITE(Exp) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(1, 15), shape, fixed_point_position) -{ - // Compute function - Tensor dst = compute_exp_qs16(shape, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS16, DataType::QS16, FixedPointOp::EXP, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance, 0); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Fixedpoint/Exp_QS8.cpp b/tests/validation/NEON/Fixedpoint/Exp_QS8.cpp deleted file mode 100644 index dae01db41e..0000000000 --- a/tests/validation/NEON/Fixedpoint/Exp_QS8.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/ReferenceCPP.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/NEFixedPoint.h" -#include "arm_compute/core/Types.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::validation; - -namespace -{ -const float tolerance = 0.0f; /**< Tolerance value for comparing reference's output against implementation's output */ - -/** Compute Neon exponential function for signed 8bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_exp_qs8(const TensorShape &shape, int fixed_point_position) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::QS8, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, DataType::QS8, 1, fixed_point_position); - - constexpr unsigned int num_elems_processed_per_iteration = 16; - Window window = calculate_max_window(*src.info(), Steps(num_elems_processed_per_iteration)); - AccessWindowHorizontal input_access(src.info(), 0, num_elems_processed_per_iteration); - AccessWindowHorizontal output_access(dst.info(), 0, num_elems_processed_per_iteration); - - update_window_and_padding(window, input_access, output_access); - output_access.set_valid_region(window, src.info()->valid_region()); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors. Keep the range between [-1.0, 1.0) so the result won't - // overflow. E.g. e^7 = 1096, which cannot be represented in QS8 - std::uniform_int_distribution<> distribution(-(1 << (fixed_point_position - 1)), (1 << (fixed_point_position - 1))); - library->fill(Accessor(src), distribution, 0); - - Iterator input(&src, window); - Iterator output(&dst, window); - - execute_window_loop(window, [&](const Coordinates & id) - { - qint8x16_t in = vld1q_s8(reinterpret_cast<const qint8_t *>(input.ptr())); - // Use saturated exp - vst1q_s8(reinterpret_cast<qint8_t *>(output.ptr()), vqexpq_qs8(in, fixed_point_position)); - }, - input, output); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_AUTO_TEST_SUITE(Exp) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(1, 7), shape, fixed_point_position) -{ - // Compute function - Tensor dst = compute_exp_qs8(shape, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS8, DataType::QS8, FixedPointOp::EXP, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance, 0); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Fixedpoint/Invsqrt_QS16.cpp b/tests/validation/NEON/Fixedpoint/Invsqrt_QS16.cpp deleted file mode 100644 index 4306a9a8ba..0000000000 --- a/tests/validation/NEON/Fixedpoint/Invsqrt_QS16.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/ReferenceCPP.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/NEFixedPoint.h" -#include "arm_compute/core/Types.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::validation; - -namespace -{ -const float tolerance = 5.0f; /**< Tolerance value for comparing reference's output against implementation's output */ - -/** Compute Neon inverse square root function for signed 16 bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_invsqrt_qs16(const TensorShape &shape, int fixed_point_position) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::QS16, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, DataType::QS16, 1, fixed_point_position); - - constexpr unsigned int num_elems_processed_per_iteration = 8; - Window window = calculate_max_window(*src.info(), Steps(num_elems_processed_per_iteration)); - AccessWindowHorizontal input_access(src.info(), 0, num_elems_processed_per_iteration); - AccessWindowHorizontal output_access(dst.info(), 0, num_elems_processed_per_iteration); - - update_window_and_padding(window, input_access, output_access); - output_access.set_valid_region(window, src.info()->valid_region()); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors. Keep the range between [1, 0x7FFF) - std::uniform_int_distribution<> distribution(1, 0x7FFF); - library->fill(Accessor(src), distribution, 0); - - Iterator input(&src, window); - Iterator output(&dst, window); - - execute_window_loop(window, [&](const Coordinates & id) - { - qint16x8_t in = vld1q_qs16(reinterpret_cast<const qint16_t *>(input.ptr())); - vst1q_qs16(reinterpret_cast<qint16_t *>(output.ptr()), vqinvsqrtq_qs16(in, fixed_point_position)); - }, - input, output); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_AUTO_TEST_SUITE(Invsqrt) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, boost::unit_test::data::xrange(1, 14), fixed_point_position) -{ - TensorShape shape(8192U); - - // Compute function - Tensor dst = compute_invsqrt_qs16(shape, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS16, DataType::QS16, FixedPointOp::INV_SQRT, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance, 0); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Fixedpoint/Invsqrt_QS8.cpp b/tests/validation/NEON/Fixedpoint/Invsqrt_QS8.cpp deleted file mode 100644 index 1a2acaf34b..0000000000 --- a/tests/validation/NEON/Fixedpoint/Invsqrt_QS8.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/ReferenceCPP.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/NEFixedPoint.h" -#include "arm_compute/core/Types.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::validation; - -namespace -{ -const float tolerance = 4.0f; /**< Tolerance value for comparing reference's output against implementation's output */ - -/** Compute Neon inverse square root function for signed 8bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_invsqrt_qs8(const TensorShape &shape, int fixed_point_position) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::QS8, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, DataType::QS8, 1, fixed_point_position); - - constexpr unsigned int num_elems_processed_per_iteration = 16; - Window window = calculate_max_window(*src.info(), Steps(num_elems_processed_per_iteration)); - AccessWindowHorizontal input_access(src.info(), 0, num_elems_processed_per_iteration); - AccessWindowHorizontal output_access(dst.info(), 0, num_elems_processed_per_iteration); - - update_window_and_padding(window, input_access, output_access); - output_access.set_valid_region(window, src.info()->valid_region()); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors. Keep the range between [1, 127). - std::uniform_int_distribution<> distribution(1, 127); - library->fill(Accessor(src), distribution, 0); - - Iterator input(&src, window); - Iterator output(&dst, window); - - execute_window_loop(window, [&](const Coordinates & id) - { - qint8x16_t in = vld1q_s8(reinterpret_cast<const qint8_t *>(input.ptr())); - vst1q_s8(reinterpret_cast<qint8_t *>(output.ptr()), vqinvsqrtq_qs8(in, fixed_point_position)); - }, - input, output); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_AUTO_TEST_SUITE(Invsqrt) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Small1DShape, SmallShapes() * boost::unit_test::data::xrange(1, 6), shape, fixed_point_position) -{ - // Compute function - Tensor dst = compute_invsqrt_qs8(shape, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS8, DataType::QS8, FixedPointOp::INV_SQRT, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance, 0); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Fixedpoint/Log_QS16.cpp b/tests/validation/NEON/Fixedpoint/Log_QS16.cpp deleted file mode 100644 index 71582d8f96..0000000000 --- a/tests/validation/NEON/Fixedpoint/Log_QS16.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/ReferenceCPP.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/NEFixedPoint.h" -#include "arm_compute/core/Types.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::validation; - -namespace -{ -const float tolerance = 7.0f; /**< Tolerance value for comparing reference's output against implementation's output */ - -/** Compute Neon logarithm function for signed 16 bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_log_qs16(const TensorShape &shape, int fixed_point_position) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::QS16, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, DataType::QS16, 1, fixed_point_position); - - constexpr unsigned int num_elems_processed_per_iteration = 8; - Window window = calculate_max_window(*src.info(), Steps(num_elems_processed_per_iteration)); - AccessWindowHorizontal input_access(src.info(), 0, num_elems_processed_per_iteration); - AccessWindowHorizontal output_access(dst.info(), 0, num_elems_processed_per_iteration); - - update_window_and_padding(window, input_access, output_access); - output_access.set_valid_region(window, src.info()->valid_region()); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors. Keep the range between [(1 << (fixed_point_position - 1), 0x3FFF) so the result won't - // overflow. - std::uniform_int_distribution<> distribution((1 << (fixed_point_position - 1)), 0x3FFF); - library->fill(Accessor(src), distribution, 0); - - Iterator input(&src, window); - Iterator output(&dst, window); - - execute_window_loop(window, [&](const Coordinates & id) - { - qint16x8_t in = vld1q_qs16(reinterpret_cast<const qint16_t *>(input.ptr())); - vst1q_qs16(reinterpret_cast<qint16_t *>(output.ptr()), vlogq_qs16(in, fixed_point_position)); - }, - input, output); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_AUTO_TEST_SUITE(Log) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(4, 14), shape, fixed_point_position) -{ - // Compute function - Tensor dst = compute_log_qs16(shape, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS16, DataType::QS16, FixedPointOp::LOG, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance, 0); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Fixedpoint/Log_QS8.cpp b/tests/validation/NEON/Fixedpoint/Log_QS8.cpp deleted file mode 100644 index cc74d12e10..0000000000 --- a/tests/validation/NEON/Fixedpoint/Log_QS8.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/ReferenceCPP.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/NEFixedPoint.h" -#include "arm_compute/core/Types.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::validation; - -namespace -{ -const float tolerance = 5; /**< Tolerance value for comparing reference's output against implementation's output */ - -/** Compute Neon logarithm function for signed 8bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_log_qs8(const TensorShape &shape, int fixed_point_position) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::QS8, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, DataType::QS8, 1, fixed_point_position); - - constexpr unsigned int num_elems_processed_per_iteration = 16; - Window window = calculate_max_window(*src.info(), Steps(num_elems_processed_per_iteration)); - AccessWindowHorizontal input_access(src.info(), 0, num_elems_processed_per_iteration); - AccessWindowHorizontal output_access(dst.info(), 0, num_elems_processed_per_iteration); - - update_window_and_padding(window, input_access, output_access); - output_access.set_valid_region(window, src.info()->valid_region()); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors. Keep the range between [(1 << (fixed_point_position - 1), 63) so the result won't - // overflow. E.g. for Q2.5 ln(0.001) = -6.9, which cannot be represented. - std::uniform_int_distribution<> distribution((1 << (fixed_point_position - 1)), 0x3F); - library->fill(Accessor(src), distribution, 0); - - Iterator input(&src, window); - Iterator output(&dst, window); - - execute_window_loop(window, [&](const Coordinates & id) - { - qint8x16_t in = vld1q_s8(reinterpret_cast<const qint8_t *>(input.ptr())); - vst1q_s8(reinterpret_cast<qint8_t *>(output.ptr()), vlogq_qs8(in, fixed_point_position)); - }, - input, output); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_AUTO_TEST_SUITE(Log) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(3, 6), shape, fixed_point_position) -{ - // Compute function - Tensor dst = compute_log_qs8(shape, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS8, DataType::QS8, FixedPointOp::LOG, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance, 0); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Fixedpoint/Reciprocal_QS16.cpp b/tests/validation/NEON/Fixedpoint/Reciprocal_QS16.cpp deleted file mode 100644 index 2081948d6c..0000000000 --- a/tests/validation/NEON/Fixedpoint/Reciprocal_QS16.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/ReferenceCPP.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/NEFixedPoint.h" -#include "arm_compute/core/Types.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::validation; - -namespace -{ -const float tolerance = 11.0f; /**< Tolerance value for comparing reference's output against implementation's output. */ - -/** Compute Neon reciprocal function for signed 16 bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_reciprocal_qs16(const TensorShape &shape, int fixed_point_position) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::QS16, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, DataType::QS16, 1, fixed_point_position); - - constexpr unsigned int num_elems_processed_per_iteration = 8; - Window window = calculate_max_window(*src.info(), Steps(num_elems_processed_per_iteration)); - AccessWindowHorizontal input_access(src.info(), 0, num_elems_processed_per_iteration); - AccessWindowHorizontal output_access(dst.info(), 0, num_elems_processed_per_iteration); - - update_window_and_padding(window, input_access, output_access); - output_access.set_valid_region(window, src.info()->valid_region()); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors. Keep the range between [15, 0x7FFF) so the result won't - // overflow. - std::uniform_int_distribution<> distribution(15, 0x7FFF); - library->fill(Accessor(src), distribution, 0); - - Iterator input(&src, window); - Iterator output(&dst, window); - - execute_window_loop(window, [&](const Coordinates & id) - { - qint16x8_t in = vld1q_qs16(reinterpret_cast<const qint16_t *>(input.ptr())); - vst1q_qs16(reinterpret_cast<qint16_t *>(output.ptr()), vqrecipq_qs16(in, fixed_point_position)); - }, - input, output); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_AUTO_TEST_SUITE(Reciprocal) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(1, 14), shape, fixed_point_position) -{ - // Compute function - Tensor dst = compute_reciprocal_qs16(shape, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS16, DataType::QS16, FixedPointOp::RECIPROCAL, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance, 0); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Fixedpoint/Reciprocal_QS8.cpp b/tests/validation/NEON/Fixedpoint/Reciprocal_QS8.cpp deleted file mode 100644 index 4b808ce3e0..0000000000 --- a/tests/validation/NEON/Fixedpoint/Reciprocal_QS8.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/ReferenceCPP.h" -#include "validation/Validation.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/NEON/NEFixedPoint.h" -#include "arm_compute/core/Types.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::validation; - -namespace -{ -const float tolerance = 3; /**< Tolerance value for comparing reference's output against implementation's output */ - -/** Compute Neon reciprocal function for signed 8bit fixed point. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_reciprocal_qs8(const TensorShape &shape, int fixed_point_position) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::QS8, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, DataType::QS8, 1, fixed_point_position); - - constexpr unsigned int num_elems_processed_per_iteration = 16; - Window window = calculate_max_window(*src.info(), Steps(num_elems_processed_per_iteration)); - AccessWindowHorizontal input_access(src.info(), 0, num_elems_processed_per_iteration); - AccessWindowHorizontal output_access(dst.info(), 0, num_elems_processed_per_iteration); - - update_window_and_padding(window, input_access, output_access); - output_access.set_valid_region(window, src.info()->valid_region()); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors. Keep the range between [15, 100) so the result won't - // overflow. E.g. for Q2.5 reciprocal(0.001) = 1000, which cannot be represented. - std::uniform_int_distribution<> distribution(15, 0x7F); - library->fill(Accessor(src), distribution, 0); - - Iterator input(&src, window); - Iterator output(&dst, window); - - execute_window_loop(window, [&](const Coordinates & id) - { - qint8x16_t in = vld1q_s8(reinterpret_cast<const qint8_t *>(input.ptr())); - vst1q_s8(reinterpret_cast<qint8_t *>(output.ptr()), vrecipq_qs8(in, fixed_point_position)); - }, - input, output); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(FixedPoint) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_AUTO_TEST_SUITE(Reciprocal) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunSmall, Small1DShape() * boost::unit_test::data::xrange(1, 6), shape, fixed_point_position) -{ - // Compute function - Tensor dst = compute_reciprocal_qs8(shape, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_operation(shape, DataType::QS8, DataType::QS8, FixedPointOp::RECIPROCAL, fixed_point_position); - - // Validate output - validate(Accessor(dst), ref_dst, tolerance, 0); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Floor.cpp b/tests/validation/NEON/Floor.cpp new file mode 100644 index 0000000000..ea16e0b21e --- /dev/null +++ b/tests/validation/NEON/Floor.cpp @@ -0,0 +1,66 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEFloor.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/FloorFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(Floor) + +template <typename T> +using NEFloorFixture = FloorValidationFixture<Tensor, Accessor, NEFloor, T>; + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEFloorFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEFloorFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/FullyConnectedLayer.cpp b/tests/validation/NEON/FullyConnectedLayer.cpp new file mode 100644 index 0000000000..55f8da97cf --- /dev/null +++ b/tests/validation/NEON/FullyConnectedLayer.cpp @@ -0,0 +1,211 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/FullyConnectedLayerDataset.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/FullyConnectedLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); +#ifdef ARM_COMPUTE_ENABLE_FP16 +constexpr AbsoluteTolerance<float> tolerance_f16(0.01f); +#endif /* ARM_COMPUTE_ENABLE_FP16*/ +/** Tolerance for fixed point operations */ +constexpr AbsoluteTolerance<float> tolerance_fixed_point(1.f); + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ +#ifdef ARM_COMPUTE_ENABLE_FP16 + DataType::F16, +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + DataType::F32, + DataType::QS8, + DataType::QS16, +}); + +const auto FullyConnectedParameters = combine(framework::dataset::make("TransposeWeights", { false, true }), framework::dataset::make("ReshapeWeights", { false, true })); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(FullyConnectedLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(framework::dataset::concat(datasets::SmallFullyConnectedLayerDataset(), datasets::LargeFullyConnectedLayerDataset()), + FullyConnectedParameters), + CNNDataTypes), + src_shape, weights_shape, bias_shape, dst_shape, transpose_weights, reshape_weights, data_type) +{ + // Set fixed point position data type allowed + int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + TensorShape ws(weights_shape); + + // Transpose weights if not done in the function + if(!reshape_weights || !transpose_weights) + { + const size_t shape_x = ws.x(); + ws.set(0, ws.y()); + ws.set(1, shape_x); + + // Weights have to be passed reshaped + // Transpose 1xW for batched version + if(!reshape_weights && dst_shape.y() > 1) + { + const float transpose_width = 16.0f / data_size_from_type(data_type); + const size_t shape_x = ws.x(); + ws.set(0, ws.y() * static_cast<unsigned int>(transpose_width)); + ws.set(1, static_cast<unsigned int>(std::ceil(shape_x / transpose_width))); + } + } + + // Create tensors + Tensor src = create_tensor<Tensor>(src_shape, data_type, 1, fixed_point_position); + Tensor weights = create_tensor<Tensor>(ws, data_type, 1, fixed_point_position); + Tensor bias = create_tensor<Tensor>(bias_shape, data_type, 1, fixed_point_position); + Tensor dst = create_tensor<Tensor>(dst_shape, data_type, 1, fixed_point_position); + + 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. + NEFullyConnectedLayer fc; + fc.configure(&src, &weights, &bias, &dst, transpose_weights, !reshape_weights); + + // Validate valid region + const ValidRegion dst_valid_region = shape_to_valid_region(dst_shape); + validate(dst.info()->valid_region(), dst_valid_region); +} + +template <typename T> +using NEFullyConnectedLayerFixture = FullyConnectedLayerValidationFixture<Tensor, Accessor, NEFullyConnectedLayer, T, true>; + +TEST_SUITE(Float) +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEFullyConnectedLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEFullyConnectedLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEFullyConnectedLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallFullyConnectedLayerDataset(), FullyConnectedParameters), + framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEFullyConnectedLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeFullyConnectedLayerDataset(), FullyConnectedParameters), + framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using NEFullyConnectedLayerFixedPointFixture = FullyConnectedLayerValidationFixedPointFixture<Tensor, Accessor, NEFullyConnectedLayer, T, true>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// Testing for fixed point position [1,6) as reciprocal limits the maximum fixed point position to 5 +FIXTURE_DATA_TEST_CASE(RunSmall, NEFullyConnectedLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fixed_point); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEFullyConnectedLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fixed_point); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14 +FIXTURE_DATA_TEST_CASE(RunSmall, NEFullyConnectedLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fixed_point); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEFullyConnectedLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeFullyConnectedLayerDataset(), + FullyConnectedParameters), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fixed_point); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/GEMM.cpp b/tests/validation/NEON/GEMM.cpp new file mode 100644 index 0000000000..05db3bbd6d --- /dev/null +++ b/tests/validation/NEON/GEMM.cpp @@ -0,0 +1,170 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEGEMM.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/LargeGEMMDataset.h" +#include "tests/datasets/SmallGEMMDataset.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/GEMMFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr AbsoluteTolerance<float> tolerance_f(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for floating point data types */ +constexpr AbsoluteTolerance<float> tolerance_q(1.0f); /**< Tolerance value for comparing reference's output against implementation's output for fixed point data types */ + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ +#ifdef ARM_COMPUTE_ENABLE_FP16 + DataType::F16, +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + DataType::F32, + DataType::QS8, + DataType::QS16, +}); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(GEMM) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(framework::dataset::concat(datasets::SmallGEMMDataset(), datasets::LargeGEMMDataset()), CNNDataTypes), + shape_a, shape_b, shape_c, output_shape, alpha, beta, data_type) +{ + // Set fixed point position data type allowed + const int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + // Create tensors + Tensor a = create_tensor<Tensor>(shape_a, data_type, 1, fixed_point_position); + Tensor b = create_tensor<Tensor>(shape_b, data_type, 1, fixed_point_position); + Tensor c = create_tensor<Tensor>(shape_c, data_type, 1, fixed_point_position); + Tensor dst = create_tensor<Tensor>(output_shape, data_type, 1, fixed_point_position); + + ARM_COMPUTE_EXPECT(a.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(b.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(c.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NEGEMM gemm; + gemm.configure(&a, &b, &c, &dst, alpha, beta); + + //TODO(COMPMID-415): Validate valid region +} + +template <typename T> +using NEGEMMFixture = GEMMValidationFixture<Tensor, Accessor, NEGEMM, T>; + +TEST_SUITE(Float) +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallGEMMDataset(), framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEGEMMFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeGEMMDataset(), framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallGEMMDataset(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEGEMMFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeGEMMDataset(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using NEGEMMFixedPointFixture = GEMMValidationFixedPointFixture<Tensor, Accessor, NEGEMM, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallGEMMDataset(), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 7))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_q); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEGEMMFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeGEMMDataset(), + framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 7))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_q); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallGEMMDataset(), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_q); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEGEMMFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeGEMMDataset(), + framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_q); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/Gaussian3x3.cpp b/tests/validation/NEON/Gaussian3x3.cpp deleted file mode 100644 index b7f9150283..0000000000 --- a/tests/validation/NEON/Gaussian3x3.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NEGaussian3x3.h" -#include "arm_compute/runtime/SubTensor.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::validation; - -namespace -{ -constexpr unsigned int filter_size = 3; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute Neon gaussian3x3 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor. - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT. - * - * @return Computed output tensor. - */ -Tensor compute_gaussian3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - // Create and configure function - NEGaussian3x3 gaussian3x3; - gaussian3x3.configure(&src, &dst, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - gaussian3x3.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Gaussian3x3) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEGaussian3x3 gaussian3x3; - gaussian3x3.configure(&src, &dst, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - validate(src.info()->valid_region(), src_valid_region); - validate(dst.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - calculator.set_border_size(1); - calculator.set_border_mode(border_mode); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-1); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - Tensor dst = compute_gaussian3x3(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_gaussian3x3(shape, border_mode, border_value); - - // Validate output - validate(Accessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - Tensor dst = compute_gaussian3x3(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_gaussian3x3(shape, border_mode, border_value); - - // Validate output - validate(Accessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Gaussian5x5.cpp b/tests/validation/NEON/Gaussian5x5.cpp deleted file mode 100644 index 7727340f66..0000000000 --- a/tests/validation/NEON/Gaussian5x5.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NEGaussian5x5.h" -#include "arm_compute/runtime/SubTensor.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::validation; - -namespace -{ -constexpr unsigned int filter_size = 5; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute Neon gaussian5x5 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor. - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT. - * - * @return Computed output tensor. - */ -Tensor compute_gaussian5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - // Create and configure function - NEGaussian5x5 gaussian5x5; - gaussian5x5.configure(&src, &dst, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - gaussian5x5.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Gaussian5x5) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEGaussian5x5 gaussian5x5; - gaussian5x5.configure(&src, &dst, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - validate(src.info()->valid_region(), src_valid_region); - validate(dst.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 16); - calculator.set_border_size(2); - calculator.set_border_mode(border_mode); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_processed_elements(8); - calculator.set_access_offset(-2); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - Tensor dst = compute_gaussian5x5(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_gaussian5x5(shape, border_mode, border_value); - - // Validate output - validate(Accessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - const uint8_t border_value = distribution(gen); - - // Compute function - Tensor dst = compute_gaussian5x5(shape, border_mode, border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_gaussian5x5(shape, border_mode, border_value); - - // Validate output - validate(Accessor(dst), ref_dst, shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size)); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/HarrisCorners.cpp b/tests/validation/NEON/HarrisCorners.cpp deleted file mode 100644 index 6793e21c34..0000000000 --- a/tests/validation/NEON/HarrisCorners.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "NEON/Helper.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NEHarrisCorners.h" -#include "arm_compute/runtime/Tensor.h" -#include "arm_compute/runtime/TensorAllocator.h" - -#include "PaddingCalculator.h" -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -/** Compute Neon Harris corners function. - * - * @param[in] shape Shape of input tensor - * @param[in] threshold Minimum threshold with which to eliminate Harris Corner scores (computed using the normalized Sobel kernel). - * @param[in] min_dist Radial Euclidean distance for the euclidean distance stage - * @param[in] sensitivity Sensitivity threshold k from the Harris-Stephens equation - * @param[in] gradient_size The gradient window size to use on the input. The implementation supports 3, 5, and 7 - * @param[in] block_size The block window size used to compute the Harris Corner score. The implementation supports 3, 5, and 7. - * @param[in] border_mode Border mode to use - * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT. - * @param[in] use_fp16 If true the FP16 kernels will be used. If false F32 kernels are used. - * - * @return Computed corners' keypoints. - */ -KeyPointArray compute_harris_corners(const TensorShape &shape, float threshold, float min_dist, float sensitivity, - int32_t gradient_size, int32_t block_size, BorderMode border_mode, uint8_t constant_border_value, bool use_fp16) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - src.info()->set_format(Format::U8); - - // Create array of keypoints - KeyPointArray corners(shape.total_size()); - - // Create harris corners configure function - NEHarrisCorners harris_corners; - harris_corners.configure(&src, threshold, min_dist, sensitivity, gradient_size, block_size, &corners, border_mode, constant_border_value, use_fp16); - - // Allocate tensors - src.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - harris_corners.run(); - - return corners; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(HarrisCorners) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (Small2DShapes() + Large2DShapes()) * BorderModes() - * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }), - shape, border_mode, gradient, block) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - src.info()->set_format(Format::U8); - - KeyPointArray corners; - - uint8_t constant_border_value = 0; - - std::mt19937 gen(user_config.seed.get()); - std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min()); - - const float threshold = real_dist(gen); - const float sensitivity = real_dist(gen); - const float max_euclidean_distance = 30.f; - - real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance); - const float min_dist = real_dist(gen); - - // 50% chance to use fp16 - bool use_fp16 = real_dist(gen) < max_euclidean_distance / 2 ? true : false; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::uniform_int_distribution<uint8_t> int_dist(0, 255); - constant_border_value = int_dist(gen); - } - - BOOST_TEST(src.info()->is_resizable()); - - // Create harris corners configure function - NEHarrisCorners harris_corners; - harris_corners.configure(&src, threshold, min_dist, sensitivity, gradient, block, &corners, border_mode, constant_border_value, use_fp16); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - - validate(src.info()->valid_region(), valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - - calculator.set_border_mode(border_mode); - calculator.set_border_size(gradient / 2); - calculator.set_access_offset(-gradient / 2); - calculator.set_accessed_elements(16); - - const PaddingSize padding = calculator.required_padding(); - - validate(src.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes() * BorderModes() * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }), shape, border_mode, gradient, block) -{ - uint8_t constant_border_value = 0; - - std::mt19937 gen(user_config.seed.get()); - std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min()); - - const float threshold = real_dist(gen); - const float sensitivity = real_dist(gen); - const float max_euclidean_distance = 30.f; - - real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance); - const float min_dist = real_dist(gen); - - // 50% chance to use fp16 - bool use_fp16 = real_dist(gen) < max_euclidean_distance / 2 ? true : false; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::uniform_int_distribution<uint8_t> int_dist(0, 255); - constant_border_value = int_dist(gen); - } - - // Compute function - KeyPointArray dst = compute_harris_corners(shape, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value, use_fp16); - - // Compute reference - KeyPointArray ref_dst = Reference::compute_reference_harris_corners(shape, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value); - - // Validate output - validate(dst, ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, Large2DShapes() * BorderModes() * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }), shape, border_mode, gradient, block) -{ - uint8_t constant_border_value = 0; - - std::mt19937 gen(user_config.seed.get()); - std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min()); - - const float threshold = real_dist(gen); - const float sensitivity = real_dist(gen); - const float max_euclidean_distance = 30.f; - - real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance); - float min_dist = real_dist(gen); - - // 50% chance to use fp16 - bool use_fp16 = real_dist(gen) < max_euclidean_distance / 2 ? true : false; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::uniform_int_distribution<uint8_t> int_dist(0, 255); - constant_border_value = int_dist(gen); - } - - // Compute function - KeyPointArray dst = compute_harris_corners(shape, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value, use_fp16); - - // Compute reference - KeyPointArray ref_dst = Reference::compute_reference_harris_corners(shape, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value); - - // Validate output - validate(dst, ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/IntegralImage.cpp b/tests/validation/NEON/IntegralImage.cpp deleted file mode 100644 index d5ad33e2a5..0000000000 --- a/tests/validation/NEON/IntegralImage.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEIntegralImage.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::validation; - -namespace -{ -/** Compute Neon integral image function. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed output tensor. - */ -Tensor compute_integral_image(const TensorShape &shape) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U32); - - // Create integral image configure function - NEIntegralImage integral_image; - integral_image.configure(&src, &dst); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - integral_image.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(IntegralImage) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, SmallShapes() + LargeShapes(), shape) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U32); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create integral image configure function - NEIntegralImage integral_image; - integral_image.configure(&src, &dst); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize src_padding = PaddingCalculator(shape.x(), 16).required_padding(); - const PaddingSize dst_padding(1, src_padding.right, 0, 1); - - validate(src.info()->padding(), src_padding); - validate(dst.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes(), shape) -{ - // Compute function - Tensor dst = compute_integral_image(shape); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_integral_image(shape); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes(), shape) -{ - // Compute function - Tensor dst = compute_integral_image(shape); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_integral_image(shape); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/L2Normalize.cpp b/tests/validation/NEON/L2Normalize.cpp new file mode 100644 index 0000000000..4f94c15767 --- /dev/null +++ b/tests/validation/NEON/L2Normalize.cpp @@ -0,0 +1,75 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEL2Normalize.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/L2NormalizeFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr RelativeTolerance tolerance_f32(0.00001f); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(L2Normalize) + +template <typename T> +using NEL2NormalizeFixture = L2NormalizeValidationFixture<Tensor, Accessor, NEL2Normalize, T>; + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEL2NormalizeFixture<float>, framework::DatasetMode::PRECOMMIT, + combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("Axis", { 0 })), framework::dataset::make("Epsilon", { 1e-12 }))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} + +FIXTURE_DATA_TEST_CASE(RunLarge, NEL2NormalizeFixture<float>, framework::DatasetMode::NIGHTLY, + combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("Axis", { 0 })), framework::dataset::make("Epsilon", { 1e-12 }))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/MeanStdDev.cpp b/tests/validation/NEON/MeanStdDev.cpp new file mode 100644 index 0000000000..42d887960e --- /dev/null +++ b/tests/validation/NEON/MeanStdDev.cpp @@ -0,0 +1,93 @@ +/* + * 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 "arm_compute/runtime/NEON/functions/NEMeanStdDev.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Macros.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/MeanStdDevFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +constexpr RelativeTolerance tolerance_rel_high_error(0.05f); +constexpr RelativeTolerance tolerance_rel_low_error(0.0005f); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(MeanStdDev) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), framework::dataset::make("DataType", DataType::U8)), shape, data_type) +{ + // Create tensors + Tensor src = create_tensor<Tensor>(shape, data_type); + + // Create output variables + float mean = 0.f; + float std_dev = 0.f; + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create configure function + NEMeanStdDev mean_std_dev_image; + mean_std_dev_image.configure(&src, &mean, &std_dev); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); + validate(src.info()->padding(), padding); +} + +template <typename T> +using NEMeanStdDevFixture = MeanStdDevValidationFixture<Tensor, Accessor, NEMeanStdDev, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, NEMeanStdDevFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate mean output + validate(_target.first, _reference.first); + + // Validate std_dev output + validate(_target.second, _reference.second, tolerance_rel_high_error); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEMeanStdDevFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), framework::dataset::make("DataType", + DataType::U8))) +{ + // Validate mean output + validate(_target.first, _reference.first, tolerance_rel_low_error); + + // Validate std_dev output + validate(_target.second, _reference.second, tolerance_rel_high_error); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/MinMaxLocation.cpp b/tests/validation/NEON/MinMaxLocation.cpp deleted file mode 100644 index a467172550..0000000000 --- a/tests/validation/NEON/MinMaxLocation.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "NEON/Helper.h" -#include "PaddingCalculator.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/NEMinMaxLocation.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::validation; - -namespace -{ -/** Compute Neon MinMaxLocation function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in Data type of first input tensor. - * @param[out] min Minimum value of tensor - * @param[out] max Maximum value of tensor - * @param[out] min_loc Array with locations of minimum values - * @param[out] max_loc Array with locations of maximum values - * @param[out] min_count Number of minimum values found - * @param[out] max_count Number of maximum values found - * - * @return Computed output tensor. - */ - -void compute_min_max_location(const TensorShape &shape, DataType dt_in, void *min, void *max, - Coordinates2DArray &min_loc, Coordinates2DArray &max_loc, uint32_t &min_count, uint32_t &max_count) -{ - // Create tensor - Tensor src = create_tensor<Tensor>(shape, dt_in); - - // Create and configure min_max_location configure function - NEMinMaxLocation min_max_loc; - min_max_loc.configure(&src, min, max, &min_loc, &max_loc, &min_count, &max_count); - - // Allocate tensors - src.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - min_max_loc.run(); -} - -void validate_configuration(const Tensor &src, TensorShape shape) -{ - BOOST_TEST(src.info()->is_resizable()); - - // Create output storage - int32_t min; - int32_t max; - Coordinates2DArray min_loc; - Coordinates2DArray max_loc; - uint32_t min_count; - uint32_t max_count; - - // Create and configure function - NEMinMaxLocation min_max_loc; - min_max_loc.configure(&src, &min, &max, &min_loc, &max_loc, &min_count, &max_count); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 1).required_padding(); - validate(src.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(MinMaxLocation) - -BOOST_AUTO_TEST_SUITE(Integer) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (Small2DShapes() + Large2DShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, dt) -{ - // Create tensor - Tensor src = create_tensor<Tensor>(shape, dt); - src.info()->set_format(dt == DataType::U8 ? Format::U8 : Format::S16); - - validate_configuration(src, shape); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, dt) -{ - // Create output storage - int32_t min; - int32_t max; - Coordinates2DArray min_loc(shape.total_size()); - Coordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - int32_t ref_min; - int32_t ref_max; - Coordinates2DArray ref_min_loc(shape.total_size()); - Coordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, dt, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - Reference::compute_reference_min_max_location(shape, dt, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, Large2DShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, dt) -{ - // Create output storage - int32_t min; - int32_t max; - Coordinates2DArray min_loc(shape.total_size()); - Coordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - int32_t ref_min; - int32_t ref_max; - Coordinates2DArray ref_min_loc(shape.total_size()); - Coordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, dt, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - Reference::compute_reference_min_max_location(shape, dt, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes() * DataType::F32, - shape, dt) -{ - // Create output storage - float min; - float max; - Coordinates2DArray min_loc(shape.total_size()); - Coordinates2DArray max_loc(shape.total_size()); - uint32_t min_count; - uint32_t max_count; - - float ref_min; - float ref_max; - Coordinates2DArray ref_min_loc(shape.total_size()); - Coordinates2DArray ref_max_loc(shape.total_size()); - uint32_t ref_min_count; - uint32_t ref_max_count; - - // Compute function - compute_min_max_location(shape, dt, &min, &max, min_loc, max_loc, min_count, max_count); - - // Compute reference - Reference::compute_reference_min_max_location(shape, dt, &ref_min, &ref_max, ref_min_loc, ref_max_loc, ref_min_count, ref_max_count); - - // Validate output - validate_min_max_loc(min, ref_min, max, ref_max, min_loc, ref_min_loc, max_loc, ref_max_loc, min_count, ref_min_count, max_count, ref_max_count); -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/NonLinearFilter.cpp b/tests/validation/NEON/NonLinearFilter.cpp deleted file mode 100644 index ff0a8e71f2..0000000000 --- a/tests/validation/NEON/NonLinearFilter.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Helpers.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NENonLinearFilter.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::validation; - -namespace -{ -/** Compute NonLinearFilter function. - * - * @param[in] input Shape of the input and output tensors. - * @param[in] function Non linear function to perform - * @param[in] mask_size Mask size. Supported sizes: 3, 5 - * @param[in] pattern Mask pattern - * @param[in] mask The given mask. Will be used only if pattern is specified to PATTERN_OTHER - * @param[in] border_mode Strategy to use for borders. - * @param[in] constant_border_value (Optional) Constant value to use for borders if border_mode is set to CONSTANT. - * - * @return Computed output tensor. - */ -Tensor compute_non_linear_filter(const TensorShape &shape, NonLinearFilterFunction function, unsigned int mask_size, - MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode, - uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - // Create and configure function - NENonLinearFilter filter; - filter.configure(&src, &dst, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - filter.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(NonLinearFilter) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) - * NonLinearFilterFunctions() * boost::unit_test::data::make({ 3U, 5U }) - * MatrixPatterns() * BorderModes(), - shape, function, mask_size, pattern, border_mode) -{ - std::mt19937 generator(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - const uint8_t constant_border_value = distribution_u8(generator); - - // Create the mask - uint8_t mask[mask_size * mask_size]; - fill_mask_from_pattern(mask, mask_size, mask_size, pattern); - const auto half_mask_size = static_cast<int>(mask_size / 2); - - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NENonLinearFilter filter; - filter.configure(&src, &dst, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, BorderSize(half_mask_size)); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), ((MatrixPattern::OTHER == pattern) ? 1 : 8)); - calculator.set_border_mode(border_mode); - calculator.set_border_size(half_mask_size); - - const PaddingSize write_padding = calculator.required_padding(PaddingCalculator::Option::EXCLUDE_BORDER); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-half_mask_size); - - const PaddingSize read_padding = calculator.required_padding(PaddingCalculator::Option::INCLUDE_BORDER); - - validate(src.info()->padding(), read_padding); - validate(dst.info()->padding(), write_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() - * NonLinearFilterFunctions() * boost::unit_test::data::make({ 3U, 5U }) - * MatrixPatterns() * BorderModes(), - shape, function, mask_size, pattern, border_mode) -{ - std::mt19937 generator(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - const uint8_t constant_border_value = distribution_u8(generator); - - // Create the mask - uint8_t mask[mask_size * mask_size]; - fill_mask_from_pattern(mask, mask_size, mask_size, pattern); - - // Compute function - Tensor dst = compute_non_linear_filter(shape, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_non_linear_filter(shape, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, BorderSize(static_cast<int>(mask_size / 2))); - - // Validate output - validate(Accessor(dst), ref_dst, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() - * NonLinearFilterFunctions() * boost::unit_test::data::make({ 3U, 5U }) - * MatrixPatterns() * BorderModes(), - shape, function, mask_size, pattern, border_mode) -{ - std::mt19937 generator(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - const uint8_t constant_border_value = distribution_u8(generator); - - // Create the mask - uint8_t mask[mask_size * mask_size]; - fill_mask_from_pattern(mask, mask_size, mask_size, pattern); - - // Compute function - Tensor dst = compute_non_linear_filter(shape, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_non_linear_filter(shape, function, mask_size, pattern, mask, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, BorderSize(static_cast<int>(mask_size / 2))); - - // Validate output - validate(Accessor(dst), ref_dst, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/NormalizationLayer.cpp b/tests/validation/NEON/NormalizationLayer.cpp new file mode 100644 index 0000000000..5d792e9e09 --- /dev/null +++ b/tests/validation/NEON/NormalizationLayer.cpp @@ -0,0 +1,144 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NENormalizationLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/NormalizationTypesDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/NormalizationLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +#ifdef ARM_COMPUTE_ENABLE_FP16 +constexpr AbsoluteTolerance<float> tolerance_f16(0.001f); +#endif /* ARM_COMPUTE_ENABLE_FP16 */ +constexpr AbsoluteTolerance<float> tolerance_f32(0.00001f); +/** Tolerance for fixed point operations */ +constexpr AbsoluteTolerance<int8_t> tolerance_qs8(2); +constexpr AbsoluteTolerance<int16_t> tolerance_qs16(3); + +/** Input data set. */ +const auto NormalizationDataset = combine(combine(combine(datasets::SmallShapes(), datasets::NormalizationTypes()), framework::dataset::make("NormalizationSize", 3, 9, 2)), + framework::dataset::make("Beta", { 0.5f, 1.f, 2.f })); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(NormalizationLayer) + +//TODO(COMPMID-415): Missing configuration? + +template <typename T> +using NENormalizationLayerFixture = NormalizationValidationFixture<Tensor, Accessor, NENormalizationLayer, T>; + +TEST_SUITE(Float) +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, NENormalizationLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(NormalizationDataset, framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NENormalizationLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(NormalizationDataset, framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NENormalizationLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(NormalizationDataset, framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NENormalizationLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(NormalizationDataset, framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using NENormalizationLayerFixedPointFixture = NormalizationValidationFixedPointFixture<Tensor, Accessor, NENormalizationLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// Testing for fixed point position [1,6) as reciprocal limits the maximum fixed point position to 5 +FIXTURE_DATA_TEST_CASE(RunSmall, NENormalizationLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(NormalizationDataset, framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs8); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NENormalizationLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(NormalizationDataset, framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs8); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14 +FIXTURE_DATA_TEST_CASE(RunSmall, NENormalizationLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(NormalizationDataset, framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NENormalizationLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(NormalizationDataset, framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs16); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/PixelWiseMultiplication.cpp b/tests/validation/NEON/PixelWiseMultiplication.cpp deleted file mode 100644 index f80944821c..0000000000 --- a/tests/validation/NEON/PixelWiseMultiplication.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.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/NEPixelWiseMultiplication.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::validation; - -namespace -{ -/** Compute Neon pixel-wise multiplication function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] scale Non-negative scale. - * @param[in] convert_policy Overflow policy of the operation. - * @param[in] rounding_policy Rounding policy of the operation. - * @param[in] fixed_point_position (Optional) Fixed point position that expresses the number of bits for the fractional part of the number. - * - * @return Computed output tensor. - */ -Tensor compute_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy, - int fixed_point_position = 0) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt_in0, 1, fixed_point_position); - Tensor src2 = create_tensor<Tensor>(shape, dt_in1, 1, fixed_point_position); - Tensor dst = create_tensor<Tensor>(shape, dt_out, 1, fixed_point_position); - - // Create and configure function - NEPixelWiseMultiplication multiply; - multiply.configure(&src1, &src2, &dst, scale, convert_policy, rounding_policy); - - // Allocate tensors - src1.allocator()->allocate(); - src2.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src1.info()->is_resizable()); - BOOST_TEST(!src2.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src1), 0); - library->fill_tensor_uniform(Accessor(src2), 1); - - // Compute function - multiply.run(); - - return dst; -} - -void validate_configuration(const Tensor &src1, const Tensor &src2, Tensor &dst, TensorShape shape, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy) -{ - BOOST_TEST(src1.info()->is_resizable()); - BOOST_TEST(src2.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEPixelWiseMultiplication multiply; - multiply.configure(&src1, &src2, &dst, scale, convert_policy, rounding_policy); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src1.info()->valid_region(), valid_region); - validate(src2.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src1.info()->padding(), padding); - validate(src2.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(PixelWiseMultiplication) - -BOOST_AUTO_TEST_SUITE(U8) -BOOST_AUTO_TEST_SUITE(Scale255) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * (1.f / 255.f) * ConvertPolicies() - * RoundingPolicy::TO_NEAREST_UP, - shape, scale, convert_policy, rounding_policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::U8); - Tensor src2 = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * (1.f / 255.f) * ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, DataType::U8, scale, convert_policy, - rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, - DataType::U8, scale, convert_policy, rounding_policy); - - // Validate output - // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion - validate(Accessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<uint8_t>::max()); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * (1.f / 255.f) * ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, DataType::U8, scale, convert_policy, - rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, - DataType::U8, scale, convert_policy, rounding_policy); - - // Validate output - // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion - validate(Accessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<uint8_t>::max()); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(ScaleOther) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) - * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, scale, convert_policy, rounding_policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::U8); - Tensor src2 = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, DataType::U8, scale, convert_policy, - rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, - DataType::U8, scale, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, DataType::U8, scale, convert_policy, - rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::U8, DataType::U8, - DataType::U8, scale, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(S16) -BOOST_AUTO_TEST_SUITE(Scale255) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * (1.f / 255.f) * ConvertPolicies() - * RoundingPolicy::TO_NEAREST_UP, - shape, dt, scale, convert_policy, rounding_policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt); - Tensor src2 = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * (1.f / 255.f) * ConvertPolicies() - * RoundingPolicy::TO_NEAREST_UP, - shape, dt, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy); - - // Validate output - // Allow tolerance value of 2.f to counteract imprecision due to 32-bit float conversion - validate(Accessor(dst), ref_dst, 2.f, 0.f, std::numeric_limits<int16_t>::max()); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * (1.f / 255.f) * ConvertPolicies() - * RoundingPolicy::TO_NEAREST_UP, - shape, dt, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, - scale, convert_policy, rounding_policy); - - // Validate output - // Allow tolerance value of 2.f to counteract imprecision due to 32-bit float conversion - validate(Accessor(dst), ref_dst, 2.f, 0.f, std::numeric_limits<int16_t>::max()); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(ScaleOther) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) - * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, dt, scale, convert_policy, rounding_policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, dt); - Tensor src2 = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst = create_tensor<Tensor>(shape, DataType::S16); - - validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, dt, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, dt, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, DataType::S16, DataType::S16, - scale, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -#ifdef ARM_COMPUTE_ENABLE_FP16 -BOOST_AUTO_TEST_SUITE(F16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) - -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * (1.f / 255.f) * ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F16, DataType::F16, DataType::F16, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F16, DataType::F16, DataType::F16, scale, convert_policy, rounding_policy); - - // Validate output - // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion - validate(Accessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<int16_t>::max()); -} - -BOOST_AUTO_TEST_SUITE_END() -#endif /* ARM_COMPUTE_ENABLE_FP16 */ - -BOOST_AUTO_TEST_SUITE(F32) -BOOST_AUTO_TEST_SUITE(Scale255) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * (1.f / 255.f) * ConvertPolicies() - * RoundingPolicy::TO_NEAREST_UP, - shape, scale, convert_policy, rounding_policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::F32); - Tensor src2 = create_tensor<Tensor>(shape, DataType::F32); - Tensor dst = create_tensor<Tensor>(shape, DataType::F32); - - validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * (1.f / 255.f) * ConvertPolicies() - * RoundingPolicy::TO_NEAREST_UP, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy); - - // Validate output - // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion - validate(Accessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<int16_t>::max()); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * (1.f / 255.f) * ConvertPolicies() - * RoundingPolicy::TO_NEAREST_UP, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, - scale, convert_policy, rounding_policy); - - // Validate output - // Allow tolerance value of 1.f to counteract imprecision due to 32-bit float conversion - validate(Accessor(dst), ref_dst, 1.f, 0.f, std::numeric_limits<int16_t>::max()); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(ScaleOther) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) - * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, scale, convert_policy, rounding_policy) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::F32); - Tensor src2 = create_tensor<Tensor>(shape, DataType::F32); - Tensor dst = create_tensor<Tensor>(shape, DataType::F32); - - validate_configuration(src1, src2, dst, shape, scale, convert_policy, rounding_policy); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * boost::unit_test::data::make({ 1.f, 1.f / 32768.f }) * ConvertPolicies() - * RoundingPolicy::TO_ZERO, - shape, scale, convert_policy, rounding_policy) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, scale, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, DataType::F32, DataType::F32, DataType::F32, - scale, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(Quantized) -BOOST_AUTO_TEST_SUITE(QS8) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * DataType::QS8 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange<int>(1, 7), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmallScale255, SmallShapes() * DataType::QS8 * (1.f / 255.f) * ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP * boost::unit_test::data::xrange(1, 7), - shape, dt, scale, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, scale, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmallScaleOther, SmallShapes() * DataType::QS8 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange(1, 7), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - const float scale = 1.f / static_cast<float>(1 << fixed_point_position); - - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, scale, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst, 1.f); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * DataType::QS8 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange<int>(1, 7), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLargeScale255, LargeShapes() * DataType::QS8 * (1.f / 255.f) * ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange(1, 7), - shape, dt, scale, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, scale, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLargeScaleOther, LargeShapes() * DataType::QS8 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange(1, 7), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - const float scale = 1.f / static_cast<float>(1 << fixed_point_position); - - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, scale, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst, 1.f); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(QS16) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * DataType::QS16 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange<int>(1, 15), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmallScale255, SmallShapes() * DataType::QS16 * (1.f / 255.f) * ConvertPolicies() * RoundingPolicy::TO_NEAREST_UP * boost::unit_test::data::xrange(1, 15), - shape, dt, scale, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, scale, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmallScaleOther, SmallShapes() * DataType::QS16 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange(1, 15), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - const float scale = 1.f / static_cast<float>(1 << fixed_point_position); - - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, scale, convert_policy, rounding_policy, fixed_point_position); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_fixed_point_pixel_wise_multiplication(shape, dt, dt, dt, scale, fixed_point_position, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst, 1.f); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * DataType::QS16 *ConvertPolicies() * RoundingPolicy::TO_ZERO * boost::unit_test::data::xrange<int>(1, 15), - shape, dt, convert_policy, rounding_policy, fixed_point_position) -{ - // Compute function - Tensor dst = compute_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_pixel_wise_multiplication(shape, dt, dt, dt, 1.f, convert_policy, rounding_policy); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/PoolingLayer.cpp b/tests/validation/NEON/PoolingLayer.cpp new file mode 100644 index 0000000000..ac5a28b527 --- /dev/null +++ b/tests/validation/NEON/PoolingLayer.cpp @@ -0,0 +1,148 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEPoolingLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/PoolingTypesDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/PoolingLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Input data set for float data types */ +const auto PoolingLayerDatasetFP = combine(combine(datasets::PoolingTypes(), framework::dataset::make("PoolingSize", { 2, 3, 7 })), + framework::dataset::make("PadStride", { PadStrideInfo(1, 1, 0, 0), PadStrideInfo(2, 1, 0, 0), PadStrideInfo(1, 2, 1, 1), PadStrideInfo(2, 2, 1, 0) })); + +/** Input data set for quantized data types */ +const auto PoolingLayerDatasetQS = combine(combine(datasets::PoolingTypes(), framework::dataset::make("PoolingSize", { 2, 3 })), + framework::dataset::make("PadStride", { PadStrideInfo(1, 1, 0, 0), PadStrideInfo(2, 1, 0, 0), PadStrideInfo(1, 2, 1, 1), PadStrideInfo(2, 2, 1, 0) })); + +constexpr AbsoluteTolerance<float> tolerance_f32(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for float types */ +#ifdef ARM_COMPUTE_ENABLE_FP16 +constexpr AbsoluteTolerance<float> tolerance_f16(0.01f); /**< Tolerance value for comparing reference's output against implementation's output for float types */ +#endif /* ARM_COMPUTE_ENABLE_FP16 */ +constexpr AbsoluteTolerance<float> tolerance_qs8(0); /**< Tolerance value for comparing reference's output against implementation's output for quantized input */ +constexpr AbsoluteTolerance<float> tolerance_qs16(0); /**< Tolerance value for comparing reference's output against implementation's output for quantized input */ +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(PoolingLayer) + +//TODO(COMPMID-415): Configuration tests? + +template <typename T> +using NEPoolingLayerFixture = PoolingLayerValidationFixture<Tensor, Accessor, NEPoolingLayer, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEPoolingLayerFixture<float>, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), combine(PoolingLayerDatasetFP, framework::dataset::make("DataType", + DataType::F32)))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEPoolingLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), combine(PoolingLayerDatasetFP, framework::dataset::make("DataType", + DataType::F32)))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() + +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEPoolingLayerFixture<half_float::half>, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), combine(PoolingLayerDatasetFP, + framework::dataset::make("DataType", DataType::F16)))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEPoolingLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), combine(PoolingLayerDatasetFP, + framework::dataset::make("DataType", DataType::F16)))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ +TEST_SUITE_END() + +template <typename T> +using NEPoolingLayerFixedPointFixture = PoolingLayerValidationFixedPointFixture<Tensor, Accessor, NEPoolingLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +FIXTURE_DATA_TEST_CASE(RunSmall, NEPoolingLayerFixedPointFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(datasets::SmallShapes(), combine(PoolingLayerDatasetQS, + framework::dataset::make("DataType", DataType::QS8))), + framework::dataset::make("FractionalBits", 1, 5))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs8); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEPoolingLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), combine(PoolingLayerDatasetQS, + framework::dataset::make("DataType", DataType::QS8))), + framework::dataset::make("FractionalBits", 1, 5))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs8); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEPoolingLayerFixedPointFixture<int16_t>, framework::DatasetMode::ALL, combine(combine(datasets::SmallShapes(), combine(PoolingLayerDatasetQS, + framework::dataset::make("DataType", DataType::QS16))), + framework::dataset::make("FractionalBits", 1, 13))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEPoolingLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), combine(PoolingLayerDatasetQS, + framework::dataset::make("DataType", DataType::QS16))), + framework::dataset::make("FractionalBits", 1, 13))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_qs16); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/QuantizationLayer.cpp b/tests/validation/NEON/QuantizationLayer.cpp new file mode 100644 index 0000000000..5c2fab4653 --- /dev/null +++ b/tests/validation/NEON/QuantizationLayer.cpp @@ -0,0 +1,98 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEQuantizationLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/QuantizationLayerFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for quantization */ +constexpr AbsoluteTolerance<uint8_t> tolerance_u8(1); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(QuantizationLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), framework::dataset::make("DataType", DataType::F32)), shape, data_type) +{ + // Create tensors + Tensor src = create_tensor<Tensor>(shape, data_type); + Tensor dst = create_tensor<Tensor>(shape, DataType::U8); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NEQuantizationLayer quant_layer; + quant_layer.configure(&src, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const PaddingSize padding = PaddingCalculator(shape.x(), 8).required_padding(); + validate(src.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using NEQuantizationLayerFixture = QuantizationValidationFixture<Tensor, Accessor, NEQuantizationLayer, T>; + +TEST_SUITE(Float) +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEQuantizationLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_u8); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEQuantizationLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_u8); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/ROIPoolingLayer.cpp b/tests/validation/NEON/ROIPoolingLayer.cpp deleted file mode 100644 index 523885d908..0000000000 --- a/tests/validation/NEON/ROIPoolingLayer.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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 "NEON/Accessor.h" -#include "NEON/ArrayAccessor.h" -#include "TypePrinter.h" -#include "arm_compute/runtime/NEON/functions/NEROIPoolingLayer.h" -#include "tests/Globals.h" -#include "tests/Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include <random> -#include <vector> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -Tensor compute_roi_pooling_layer(const TensorShape &shape, DataType dt, const std::vector<ROI> &rois, ROIPoolingLayerInfo pool_info) -{ - TensorShape shape_dst; - shape_dst.set(0, pool_info.pooled_width()); - shape_dst.set(1, pool_info.pooled_height()); - shape_dst.set(2, shape.z()); - shape_dst.set(3, rois.size()); - - // Create tensors - Tensor src = create_tensor<Tensor>(shape, dt); - Tensor dst = create_tensor<Tensor>(shape_dst, dt); - - // Create ROI array - Array<ROI> rois_array(rois.size()); - fill_array(ArrayAccessor<ROI>(rois_array), rois); - - // Create and configure function - NEROIPoolingLayer roi_pool; - roi_pool.configure(&src, &rois_array, &dst, pool_info); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - std::uniform_real_distribution<> distribution(-1, 1); - library->fill(Accessor(src), distribution, 0); - - // Compute function - roi_pool.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(ROIPoolingLayer) - -BOOST_AUTO_TEST_SUITE(Float) -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, CNNFloatDataTypes() * boost::unit_test::data::make({ 10, 20, 40 }) * boost::unit_test::data::make({ 7, 9 }) * boost::unit_test::data::make({ 1.f / 8.f, 1.f / 16.f }), - dt, num_rois, roi_pool_size, roi_scale) -{ - TensorShape shape(50U, 47U, 2U, 3U); - ROIPoolingLayerInfo pool_info(roi_pool_size, roi_pool_size, roi_scale); - - // Construct ROI vector - std::vector<ROI> rois = generate_random_rois(shape, pool_info, num_rois, user_config.seed); - - // Compute function - Tensor dst = compute_roi_pooling_layer(shape, dt, rois, pool_info); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_roi_pooling_layer(shape, dt, rois, pool_info); - - // Validate output - validate(Accessor(dst), ref_dst); -} -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/ReductionOperation.cpp b/tests/validation/NEON/ReductionOperation.cpp new file mode 100644 index 0000000000..4ea71a6336 --- /dev/null +++ b/tests/validation/NEON/ReductionOperation.cpp @@ -0,0 +1,75 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEReductionOperation.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ReductionOperationDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ReductionOperationFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr RelativeTolerance tolerance_f32(0.00001f); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(ReductionOperation) + +template <typename T> +using NEReductionOperationFixture = ReductionOperationValidationFixture<Tensor, Accessor, NEReductionOperation, T>; + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEReductionOperationFixture<float>, framework::DatasetMode::PRECOMMIT, + combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("Axis", { 0 })), datasets::ReductionOperations())) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEReductionOperationFixture<float>, framework::DatasetMode::NIGHTLY, + combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("Axis", { 0 })), datasets::ReductionOperations())) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/Scale.cpp b/tests/validation/NEON/Scale.cpp new file mode 100644 index 0000000000..2fbd7c7014 --- /dev/null +++ b/tests/validation/NEON/Scale.cpp @@ -0,0 +1,127 @@ +/* + * 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 "arm_compute/core/Helpers.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEScale.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/BorderModeDataset.h" +#include "tests/datasets/InterpolationPolicyDataset.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Helpers.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ScaleFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(Scale) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)), + framework::dataset::make("InterpolationPolicy", { InterpolationPolicy::NEAREST_NEIGHBOR, InterpolationPolicy::BILINEAR })), + datasets::BorderModes()), + shape, data_type, policy, border_mode) +{ + std::mt19937 generator(library->seed()); + std::uniform_real_distribution<float> distribution_float(0.25, 2); + const float scale_x = distribution_float(generator); + const float scale_y = distribution_float(generator); + uint8_t constant_border_value = 0; + if(border_mode == BorderMode::CONSTANT) + { + std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); + constant_border_value = distribution_u8(generator); + } + + // Create tensors + Tensor src = create_tensor<Tensor>(shape, data_type); + TensorShape shape_scaled(shape); + shape_scaled.set(0, shape[0] * scale_x); + shape_scaled.set(1, shape[1] * scale_y); + Tensor dst = create_tensor<Tensor>(shape_scaled, data_type); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NEScale nescale; + nescale.configure(&src, &dst, policy, border_mode, constant_border_value); + + // Validate valid region + const ValidRegion dst_valid_region = calculate_valid_region_scale(*(src.info()), shape_scaled, policy, BorderSize(1), (border_mode == BorderMode::UNDEFINED)); + + validate(dst.info()->valid_region(), dst_valid_region); + + // Validate padding + PaddingCalculator calculator(shape_scaled.x(), 16); + calculator.set_border_mode(border_mode); + + const PaddingSize read_padding(1); + const PaddingSize write_padding = calculator.required_padding(PaddingCalculator::Option::EXCLUDE_BORDER); + validate(src.info()->padding(), read_padding); + validate(dst.info()->padding(), write_padding); +} + +template <typename T> +using NEScaleFixture = ScaleValidationFixture<Tensor, Accessor, NEScale, T>; + +FIXTURE_DATA_TEST_CASE(RunSmall, NEScaleFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::U8)), + framework::dataset::make("InterpolationPolicy", { InterpolationPolicy::NEAREST_NEIGHBOR, InterpolationPolicy::BILINEAR })), + datasets::BorderModes())) +{ + //Create valid region + TensorInfo src_info(_shape, 1, _data_type); + ValidRegion valid_region = calculate_valid_region_scale(src_info, _reference.shape(), _policy, BorderSize(1), (_border_mode == BorderMode::UNDEFINED)); + + // Validate output + validate(Accessor(_target), _reference, valid_region); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEScaleFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::U8)), + framework::dataset::make("InterpolationPolicy", { InterpolationPolicy::NEAREST_NEIGHBOR, InterpolationPolicy::BILINEAR })), + datasets::BorderModes())) +{ + //Create valid region + TensorInfo src_info(_shape, 1, _data_type); + ValidRegion valid_region = calculate_valid_region_scale(src_info, _reference.shape(), _policy, BorderSize(1), (_border_mode == BorderMode::UNDEFINED)); + + // Validate output + validate(Accessor(_target), _reference, valid_region); +} + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/Sobel3x3.cpp b/tests/validation/NEON/Sobel3x3.cpp deleted file mode 100644 index 74a3144de4..0000000000 --- a/tests/validation/NEON/Sobel3x3.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NESobel3x3.h" -#include "arm_compute/runtime/Tensor.h" -#include "arm_compute/runtime/TensorAllocator.h" - -#include "PaddingCalculator.h" -#include "boost_wrapper.h" - -#include <random> -#include <string> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -constexpr unsigned int filter_size = 3; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute Neon Sobel 3x3 function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed output tensor. - */ -std::pair<Tensor, Tensor> compute_sobel_3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst_x = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst_y = create_tensor<Tensor>(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - // Create sobel image configure function - NESobel3x3 sobel_3x3; - sobel_3x3.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst_x.allocator()->allocate(); - dst_y.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst_x.info()->is_resizable()); - BOOST_TEST(!dst_y.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - sobel_3x3.run(); - - return std::make_pair(std::move(dst_x), std::move(dst_y)); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Sobel3x3) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst_x = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst_y = create_tensor<Tensor>(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst_x.info()->is_resizable()); - BOOST_TEST(dst_y.info()->is_resizable()); - - // Create sobel 3x3 configure function - NESobel3x3 sobel_3x3; - sobel_3x3.configure(&src, &dst_x, &dst_y, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst_x.info()->valid_region(), dst_valid_region); - validate(dst_y.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 8); - - calculator.set_border_mode(border_mode); - calculator.set_border_size(1); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_accessed_elements(16); - calculator.set_access_offset(-1); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst_x.info()->padding(), dst_padding); - validate(dst_y.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair<Tensor, Tensor> dst = compute_sobel_3x3(shape, border_mode, constant_border_value); - - // Compute reference - std::pair<RawTensor, RawTensor> ref_dst = Reference::compute_reference_sobel_3x3(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(Accessor(dst.first), ref_dst.first, valid_region); - validate(Accessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair<Tensor, Tensor> dst = compute_sobel_3x3(shape, border_mode, constant_border_value); - - // Compute reference - std::pair<RawTensor, RawTensor> ref_dst = Reference::compute_reference_sobel_3x3(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(Accessor(dst.first), ref_dst.first, valid_region); - validate(Accessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Sobel5x5.cpp b/tests/validation/NEON/Sobel5x5.cpp deleted file mode 100644 index d4d48f6afa..0000000000 --- a/tests/validation/NEON/Sobel5x5.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NESobel5x5.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::validation; - -namespace -{ -constexpr unsigned int filter_size = 5; /** Size of the kernel/filter in number of elements. */ -constexpr BorderSize border_size(filter_size / 2); /** Border size of the kernel/filter around its central element. */ - -/** Compute Neon Sobel 5x5 function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed output tensor. - */ -std::pair<Tensor, Tensor> compute_sobel_5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst_x = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst_y = create_tensor<Tensor>(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - // Create sobel image configure function - NESobel5x5 sobel_5x5; - sobel_5x5.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst_x.allocator()->allocate(); - dst_y.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst_x.info()->is_resizable()); - BOOST_TEST(!dst_y.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - sobel_5x5.run(); - - return std::make_pair(std::move(dst_x), std::move(dst_y)); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Sobel5x5) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * BorderModes(), shape, border_mode) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst_x = create_tensor<Tensor>(shape, DataType::S16); - Tensor dst_y = create_tensor<Tensor>(shape, DataType::S16); - - src.info()->set_format(Format::U8); - dst_x.info()->set_format(Format::S16); - dst_y.info()->set_format(Format::S16); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst_x.info()->is_resizable()); - BOOST_TEST(dst_y.info()->is_resizable()); - - // Create sobel 5x5 configure function - NESobel5x5 sobel_5x5; - sobel_5x5.configure(&src, &dst_x, &dst_y, border_mode); - - // Validate valid region - const ValidRegion src_valid_region = shape_to_valid_region(shape); - const ValidRegion dst_valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - validate(src.info()->valid_region(), src_valid_region); - validate(dst_x.info()->valid_region(), dst_valid_region); - validate(dst_y.info()->valid_region(), dst_valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 16); - - calculator.set_border_mode(border_mode); - calculator.set_border_size(2); - - const PaddingSize dst_padding = calculator.required_padding(); - - calculator.set_processed_elements(8); - calculator.set_access_offset(-2); - - const PaddingSize src_padding = calculator.required_padding(); - - validate(src.info()->padding(), src_padding); - validate(dst_x.info()->padding(), dst_padding); - validate(dst_y.info()->padding(), dst_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair<Tensor, Tensor> dst = compute_sobel_5x5(shape, border_mode, constant_border_value); - - // Compute reference - std::pair<RawTensor, RawTensor> ref_dst = Reference::compute_reference_sobel_5x5(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(Accessor(dst.first), ref_dst.first, valid_region); - validate(Accessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() * BorderModes(), shape, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution(0, 255); - constant_border_value = distribution(gen); - } - - // Compute function - std::pair<Tensor, Tensor> dst = compute_sobel_5x5(shape, border_mode, constant_border_value); - - // Compute reference - std::pair<RawTensor, RawTensor> ref_dst = Reference::compute_reference_sobel_5x5(shape, border_mode, constant_border_value); - - // Calculate valid region - const ValidRegion valid_region = shape_to_valid_region(shape, border_mode == BorderMode::UNDEFINED, border_size); - - // Validate output - validate(Accessor(dst.first), ref_dst.first, valid_region); - validate(Accessor(dst.second), ref_dst.second, valid_region); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/SoftmaxLayer.cpp b/tests/validation/NEON/SoftmaxLayer.cpp new file mode 100644 index 0000000000..36f1881147 --- /dev/null +++ b/tests/validation/NEON/SoftmaxLayer.cpp @@ -0,0 +1,175 @@ +/* + * 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 "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NESoftmaxLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/SoftmaxLayerFixture.h" +#include "tests/validation/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +/** Tolerance for float operations */ +constexpr AbsoluteTolerance<float> tolerance_f32(0.000001f); +#ifdef ARM_COMPUTE_ENABLE_FP16 +constexpr AbsoluteTolerance<float> tolerance_f16(0.0001f); +#endif /* ARM_COMPUTE_ENABLE_FP16*/ +/** Tolerance for fixed point operations */ +constexpr AbsoluteTolerance<int8_t> tolerance_fixed_point(2); + +/** CNN data types */ +const auto CNNDataTypes = framework::dataset::make("DataType", +{ +#ifdef ARM_COMPUTE_ENABLE_FP16 + DataType::F16, +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + DataType::F32, + DataType::QS8, + DataType::QS16, +}); +} // namespace + +TEST_SUITE(NEON) +TEST_SUITE(SoftmaxLayer) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), CNNDataTypes), shape, data_type) +{ + // Set fixed point position data type allowed + const int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0; + + // Create tensors + Tensor src = create_tensor<Tensor>(shape, data_type, 1, fixed_point_position); + Tensor dst = create_tensor<Tensor>(shape, data_type, 1, fixed_point_position); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Create and configure function + NESoftmaxLayer smx_layer; + smx_layer.configure(&src, &dst); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(shape); + validate(src.info()->valid_region(), valid_region); + validate(dst.info()->valid_region(), valid_region); + + // Validate padding + const int step = 16 / data_size_from_type(data_type); + const PaddingSize padding = PaddingCalculator(shape.x(), step).required_padding(); + validate(src.info()->padding(), padding); + validate(dst.info()->padding(), padding); +} + +template <typename T> +using NESoftmaxLayerFixture = SoftmaxValidationFixture<Tensor, Accessor, NESoftmaxLayer, T>; + +TEST_SUITE(Float) +#ifdef ARM_COMPUTE_ENABLE_FP16 +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, NESoftmaxLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NESoftmaxLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F16))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f16); +} +TEST_SUITE_END() +#endif /* ARM_COMPUTE_ENABLE_FP16 */ + +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NESoftmaxLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NESoftmaxLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", DataType::F32))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_f32); +} +TEST_SUITE_END() +TEST_SUITE_END() + +template <typename T> +using NESoftmaxLayerFixedPointFixture = SoftmaxValidationFixedPointFixture<Tensor, Accessor, NESoftmaxLayer, T>; + +TEST_SUITE(Quantized) +TEST_SUITE(QS8) +// Testing for fixed point position [1,6) as reciprocal limits the maximum fixed point position to 5 +FIXTURE_DATA_TEST_CASE(RunSmall, NESoftmaxLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fixed_point); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NESoftmaxLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fixed_point); +} +TEST_SUITE_END() + +TEST_SUITE(QS16) +// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14 +FIXTURE_DATA_TEST_CASE(RunSmall, NESoftmaxLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fixed_point); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NESoftmaxLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) +{ + // Validate output + validate(Accessor(_target), _reference, tolerance_fixed_point); +} +TEST_SUITE_END() +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/TableLookup.cpp b/tests/validation/NEON/TableLookup.cpp deleted file mode 100644 index 70b767eb16..0000000000 --- a/tests/validation/NEON/TableLookup.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "NEON/Helper.h" -#include "NEON/LutAccessor.h" -#include "PaddingCalculator.h" -#include "RawLutAccessor.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Helpers.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/NETableLookup.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::validation; - -namespace -{ -/** Compute Table Lookup function. - * - * @param[in] shape Shape of the input tensors - * @param[in] data_type Datatype of the input/output tensors - * @param[in] lut The input LUT. - * - * @return Computed output tensor. - */ -Tensor compute_table_lookup(const TensorShape &shape, DataType data_type, Lut &lut) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, data_type); - Tensor dst = create_tensor<Tensor>(shape, data_type); - - // Create and configure function - NETableLookup table_lookup; - table_lookup.configure(&src, &lut, &dst); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - table_lookup.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(TableLookup) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, data_type) -{ - //Create Lut - const int num_elem = (data_type == DataType::U8) ? std::numeric_limits<uint8_t>::max() + 1 : std::numeric_limits<int16_t>::max() - std::numeric_limits<int16_t>::lowest() + 1; - Lut lut(num_elem, data_type); - - if(data_type == DataType::U8) - { - fill_lookuptable(LutAccessor<uint8_t>(lut)); - } - else - { - fill_lookuptable(LutAccessor<int16_t>(lut)); - } - - // Create tensors - Tensor src = create_tensor<Tensor>(shape, data_type); - Tensor dst = create_tensor<Tensor>(shape, data_type); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NETableLookup table_lookup; - table_lookup.configure(&src, &lut, &dst); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, - SmallShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, data_type) -{ - //Create Lut - const int num_elem = (data_type == DataType::U8) ? std::numeric_limits<uint8_t>::max() + 1 : std::numeric_limits<int16_t>::max() - std::numeric_limits<int16_t>::lowest() + 1; - Lut lut(num_elem, data_type); - - if(data_type == DataType::U8) - { - //Create rawLut - std::map<uint8_t, uint8_t> rawlut; - - //Fill the Lut - fill_lookuptable(LutAccessor<uint8_t>(lut)); - fill_lookuptable(RawLutAccessor<uint8_t>(rawlut)); - - // Compute function - Tensor dst = compute_table_lookup(shape, data_type, lut); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_table_lookup(shape, data_type, rawlut); - - // Validate output - validate(Accessor(dst), ref_dst); - } - else - { - //Create rawLut - std::map<int16_t, int16_t> rawlut; - - //Fill the Lut - fill_lookuptable(LutAccessor<int16_t>(lut)); - fill_lookuptable(RawLutAccessor<int16_t>(rawlut)); - - // Compute function - Tensor dst = compute_table_lookup(shape, data_type, lut); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_table_lookup(shape, data_type, rawlut); - - // Validate output - validate(Accessor(dst), ref_dst); - } -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, - LargeShapes() * boost::unit_test::data::make({ DataType::U8, DataType::S16 }), - shape, data_type) -{ - //Create Lut - const int num_elem = (data_type == DataType::U8) ? std::numeric_limits<uint8_t>::max() + 1 : std::numeric_limits<int16_t>::max() - std::numeric_limits<int16_t>::lowest() + 1; - Lut lut(num_elem, data_type); - - if(data_type == DataType::U8) - { - //Create rawLut - std::map<uint8_t, uint8_t> rawlut; - - //Fill the Lut - fill_lookuptable(LutAccessor<uint8_t>(lut)); - fill_lookuptable(RawLutAccessor<uint8_t>(rawlut)); - - // Compute function - Tensor dst = compute_table_lookup(shape, data_type, lut); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_table_lookup(shape, data_type, rawlut); - - // Validate output - validate(Accessor(dst), ref_dst); - } - else - { - //Create rawLut - std::map<int16_t, int16_t> rawlut; - - //Fill the Lut - fill_lookuptable(LutAccessor<int16_t>(lut)); - fill_lookuptable(RawLutAccessor<int16_t>(rawlut)); - - // Compute function - Tensor dst = compute_table_lookup(shape, data_type, lut); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_table_lookup(shape, data_type, rawlut); - - // Validate output - validate(Accessor(dst), ref_dst); - } -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/Threshold.cpp b/tests/validation/NEON/Threshold.cpp deleted file mode 100644 index f5382d4bfa..0000000000 --- a/tests/validation/NEON/Threshold.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "dataset/ThresholdDataset.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/NEThreshold.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::validation; - -namespace -{ -/** Compute Threshold function. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] threshold Threshold. When the threshold type is RANGE, this is used as the lower threshold. - * @param[in] false_value value to set when the condition is not respected. - * @param[in] true_value value to set when the condition is respected. - * @param[in] type Thresholding type. Either RANGE or BINARY. - * @param[in] upper Upper threshold. Only used when the thresholding type is RANGE. - * - * @return Computed output tensor. - */ -Tensor compute_threshold(const TensorShape &shape, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper) -{ - // Create tensors - Tensor src1 = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - // Create and configure function - NEThreshold thrsh; - thrsh.configure(&src1, &dst, threshold, false_value, true_value, type, upper); - - // Allocate tensors - src1.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src1.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src1), 0); - - // Compute function - thrsh.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(Threshold) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, - (SmallShapes() + LargeShapes()) * ThresholdDataset(), - shape, thrshConf) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEThreshold thrsh; - thrsh.configure(&src, &dst, thrshConf.threshold, thrshConf.false_value, thrshConf.true_value, thrshConf.type, thrshConf.upper); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding(); - validate(src.info()->padding(), padding); - validate(dst.info()->padding(), padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, - SmallShapes() * ThresholdDataset(), - shape, thrshConf) -{ - // Compute function - Tensor dst = compute_threshold(shape, thrshConf.threshold, thrshConf.false_value, thrshConf.true_value, thrshConf.type, thrshConf.upper); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_threshold(shape, thrshConf.threshold, thrshConf.false_value, thrshConf.true_value, thrshConf.type, thrshConf.upper); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, - LargeShapes() * ThresholdDataset(), - shape, thrshConf) -{ - // Compute function - Tensor dst = compute_threshold(shape, thrshConf.threshold, thrshConf.false_value, thrshConf.true_value, thrshConf.type, thrshConf.upper); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_threshold(shape, thrshConf.threshold, thrshConf.false_value, thrshConf.true_value, thrshConf.type, thrshConf.upper); - - // Validate output - validate(Accessor(dst), ref_dst); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/NEON/WarpPerspective.cpp b/tests/validation/NEON/WarpPerspective.cpp deleted file mode 100644 index 2c102ea37e..0000000000 --- a/tests/validation/NEON/WarpPerspective.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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 "AssetsLibrary.h" -#include "Globals.h" -#include "NEON/Accessor.h" -#include "PaddingCalculator.h" -#include "TypePrinter.h" -#include "Utils.h" -#include "validation/Datasets.h" -#include "validation/Helpers.h" -#include "validation/Reference.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NEWarpPerspective.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::validation; - -namespace -{ -/** Compute Warp Perspective function. - * - * @param[in] input Shape of the input and output tensors. - * @param[in] matrix The perspective matrix. Must be 3x3 of type float. - * @param[in] policy The interpolation type. - * @param[in] border_mode Strategy to use for borders. - * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT. - * - * @return Computed output tensor. - */ -Tensor compute_warp_perspective(const TensorShape &shape, const float *matrix, InterpolationPolicy policy, - BorderMode border_mode, uint8_t constant_border_value) -{ - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - // Create and configure function - NEWarpPerspective warp_perspective; - warp_perspective.configure(&src, &dst, matrix, policy, border_mode, constant_border_value); - - // Allocate tensors - src.allocator()->allocate(); - dst.allocator()->allocate(); - - BOOST_TEST(!src.info()->is_resizable()); - BOOST_TEST(!dst.info()->is_resizable()); - - // Fill tensors - library->fill_tensor_uniform(Accessor(src), 0); - - // Compute function - warp_perspective.run(); - - return dst; -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(NEON) -BOOST_AUTO_TEST_SUITE(WarpPerspective) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Configuration, (SmallShapes() + LargeShapes()) - * boost::unit_test::data::make({ InterpolationPolicy::BILINEAR, InterpolationPolicy::NEAREST_NEIGHBOR }) * BorderModes(), - shape, policy, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - constant_border_value = distribution_u8(gen); - } - - // Create the matrix - std::array<float, 9> matrix; - fill_warp_matrix<9>(matrix, 3, 3); - - // Create tensors - Tensor src = create_tensor<Tensor>(shape, DataType::U8); - Tensor dst = create_tensor<Tensor>(shape, DataType::U8); - - BOOST_TEST(src.info()->is_resizable()); - BOOST_TEST(dst.info()->is_resizable()); - - // Create and configure function - NEWarpPerspective warp_perspective; - warp_perspective.configure(&src, &dst, matrix.data(), policy, border_mode, constant_border_value); - - // Validate valid region - const ValidRegion valid_region = shape_to_valid_region(shape); - - validate(src.info()->valid_region(), valid_region); - validate(dst.info()->valid_region(), valid_region); - - // Validate padding - PaddingCalculator calculator(shape.x(), 1); - calculator.set_border_mode(border_mode); - calculator.set_border_size(1); - - const PaddingSize read_padding(1); - const PaddingSize write_padding = calculator.required_padding(); - - validate(src.info()->padding(), read_padding); - validate(dst.info()->padding(), write_padding); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_DATA_TEST_CASE(RunSmall, SmallShapes() - * boost::unit_test::data::make({ InterpolationPolicy::BILINEAR, InterpolationPolicy::NEAREST_NEIGHBOR }) - * BorderModes(), - shape, policy, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - constant_border_value = distribution_u8(gen); - } - - // Create the valid mask Tensor - RawTensor valid_mask(shape, DataType::U8); - - // Create the matrix - std::array<float, 9> matrix; - fill_warp_matrix<9>(matrix, 3, 3); - - // Compute function - Tensor dst = compute_warp_perspective(shape, matrix.data(), policy, border_mode, constant_border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_warp_perspective(shape, valid_mask, matrix.data(), policy, border_mode, constant_border_value); - - // Validate output - validate(Accessor(dst), ref_dst, valid_mask, 1, 0.2f); -} -BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RunLarge, LargeShapes() - * boost::unit_test::data::make({ InterpolationPolicy::NEAREST_NEIGHBOR, InterpolationPolicy::BILINEAR }) * BorderModes(), - shape, policy, border_mode) -{ - uint8_t constant_border_value = 0; - - // Generate a random constant value if border_mode is constant - if(border_mode == BorderMode::CONSTANT) - { - std::mt19937 gen(user_config.seed.get()); - std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); - constant_border_value = distribution_u8(gen); - } - - // Create the valid mask Tensor - RawTensor valid_mask(shape, DataType::U8); - - // Create the matrix - std::array<float, 9> matrix; - fill_warp_matrix<9>(matrix, 3, 3); - - // Compute function - Tensor dst = compute_warp_perspective(shape, matrix.data(), policy, border_mode, constant_border_value); - - // Compute reference - RawTensor ref_dst = Reference::compute_reference_warp_perspective(shape, valid_mask, matrix.data(), policy, border_mode, constant_border_value); - - // Validate output - validate(Accessor(dst), ref_dst, valid_mask, 1, 0.2f); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/Reference.cpp b/tests/validation/Reference.cpp deleted file mode 100644 index a621fea8a9..0000000000 --- a/tests/validation/Reference.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/* - * 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 "Reference.h" - -#include "AssetsLibrary.h" -#include "Globals.h" -#include "Helpers.h" -#include "ReferenceCPP.h" -#include "validation/Helpers.h" - -#include <random> -#include <vector> - -using namespace arm_compute::test; - -#ifndef DOXYGEN_SKIP_THIS -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -std::pair<RawTensor, RawTensor> Reference::compute_reference_sobel_3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, Format::U8); - RawTensor ref_dst_x(shape, Format::S16); - RawTensor ref_dst_y(shape, Format::S16); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::sobel_3x3(ref_src, ref_dst_x, ref_dst_y, border_mode, constant_border_value); - - return std::make_pair(ref_dst_x, ref_dst_y); -} - -std::pair<RawTensor, RawTensor> Reference::compute_reference_sobel_5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, Format::U8); - RawTensor ref_dst_x(shape, Format::S16); - RawTensor ref_dst_y(shape, Format::S16); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::sobel_5x5(ref_src, ref_dst_x, ref_dst_y, border_mode, constant_border_value); - - return std::make_pair(ref_dst_x, ref_dst_y); -} -void Reference::compute_reference_min_max_location(const TensorShape &shape, DataType dt_in, void *min, void *max, IArray<Coordinates2D> &min_loc, IArray<Coordinates2D> &max_loc, - uint32_t &min_count, uint32_t &max_count) -{ - // Create reference - RawTensor ref_src(shape, dt_in); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::min_max_location(ref_src, min, max, min_loc, max_loc, min_count, max_count); -} - -KeyPointArray Reference::compute_reference_harris_corners(const TensorShape &shape, float threshold, float min_dist, float sensitivity, - int32_t gradient_size, int32_t block_size, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, Format::U8); - RawTensor raw_Gx(shape, (gradient_size == 7) ? Format::S32 : Format::S16); - RawTensor raw_Gy(shape, (gradient_size == 7) ? Format::S32 : Format::S16); - RawTensor raw_candidates(shape, Format::F32); - RawTensor raw_non_maxima(shape, Format::F32); - - KeyPointArray corners(shape.total_size()); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::harris_corners(ref_src, raw_Gx, raw_Gy, raw_candidates, raw_non_maxima, threshold, min_dist, sensitivity, gradient_size, block_size, corners, border_mode, constant_border_value); - - return corners; -} - -RawTensor Reference::compute_reference_integral_image(const TensorShape &shape) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::U32); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::integral_image(ref_src, ref_dst); - - return ref_dst; -} - -RawTensor Reference::compute_reference_absolute_difference(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out) -{ - // Create reference - RawTensor ref_src1(shape, dt_in0); - RawTensor ref_src2(shape, dt_in1); - RawTensor ref_dst(shape, dt_out); - - // Fill reference - library->fill_tensor_uniform(ref_src1, 0); - library->fill_tensor_uniform(ref_src2, 1); - - // Compute reference - ReferenceCPP::absolute_difference(ref_src1, ref_src2, ref_dst); - - return ref_dst; -} - -RawTensor Reference::compute_reference_accumulate(const TensorShape &shape) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::S16); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - library->fill_tensor_uniform(ref_dst, 1); - - // Compute reference - ReferenceCPP::accumulate(ref_src, ref_dst); - - return ref_dst; -} - -RawTensor Reference::compute_reference_accumulate_squared(const TensorShape &shape, uint32_t shift) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::S16); - - // Fill reference - // ref_dst tensor filled with non-negative values - library->fill_tensor_uniform(ref_src, 0); - library->fill_tensor_uniform(ref_dst, 1, static_cast<int16_t>(0), std::numeric_limits<int16_t>::max()); - - // Compute reference - ReferenceCPP::accumulate_squared(ref_src, ref_dst, shift); - - return ref_dst; -} - -RawTensor Reference::compute_reference_accumulate_weighted(const TensorShape &shape, float alpha) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::U8); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - library->fill_tensor_uniform(ref_dst, 1); - - // Compute reference - ReferenceCPP::accumulate_weighted(ref_src, ref_dst, alpha); - - return ref_dst; -} - -RawTensor Reference::compute_reference_arithmetic_addition(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy convert_policy, int fixed_point_position) -{ - // Create reference - RawTensor ref_src1(shape, dt_in0, 1, fixed_point_position); - RawTensor ref_src2(shape, dt_in1, 1, fixed_point_position); - RawTensor ref_dst(shape, dt_out, 1, fixed_point_position); - - // Fill reference - library->fill_tensor_uniform(ref_src1, 0); - library->fill_tensor_uniform(ref_src2, 1); - - // Compute reference - ReferenceCPP::arithmetic_addition(ref_src1, ref_src2, ref_dst, convert_policy); - - return ref_dst; -} - -RawTensor Reference::compute_reference_arithmetic_subtraction(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy convert_policy, int fixed_point_position) -{ - // Create reference - RawTensor ref_src1(shape, dt_in0, 1, fixed_point_position); - RawTensor ref_src2(shape, dt_in1, 1, fixed_point_position); - RawTensor ref_dst(shape, dt_out, 1, fixed_point_position); - - // Fill reference - library->fill_tensor_uniform(ref_src1, 0); - library->fill_tensor_uniform(ref_src2, 1); - - // Compute reference - ReferenceCPP::arithmetic_subtraction(ref_src1, ref_src2, ref_dst, convert_policy); - - return ref_dst; -} - -RawTensor Reference::compute_reference_box3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::U8); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::box3x3(ref_src, ref_dst, border_mode, constant_border_value); - - return ref_dst; -} - -RawTensor Reference::compute_reference_depth_convert(const TensorShape &shape, DataType dt_in, DataType dt_out, ConvertPolicy policy, - uint32_t shift, uint32_t fixed_point_position_in, uint32_t fixed_point_position_out) -{ - RawTensor ref_src(shape, dt_in, 1, fixed_point_position_in); - RawTensor ref_dst(shape, dt_out, 1, fixed_point_position_out); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::depth_convert(ref_src, ref_dst, policy, shift); - - return ref_dst; -} - -RawTensor Reference::compute_reference_gaussian3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::U8); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::gaussian3x3(ref_src, ref_dst, border_mode, constant_border_value); - - return ref_dst; -} - -RawTensor Reference::compute_reference_gaussian5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::U8); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::gaussian5x5(ref_src, ref_dst, border_mode, constant_border_value); - - return ref_dst; -} - -RawTensor Reference::compute_reference_non_linear_filter(const TensorShape &shape, NonLinearFilterFunction function, unsigned int mask_size, - MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode, uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::U8); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::non_linear_filter(ref_src, ref_dst, function, mask_size, pattern, mask, border_mode, constant_border_value); - - return ref_dst; -} - -RawTensor Reference::compute_reference_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, ConvertPolicy convert_policy, - RoundingPolicy rounding_policy) -{ - // Create reference - RawTensor ref_src1(shape, dt_in0); - RawTensor ref_src2(shape, dt_in1); - RawTensor ref_dst(shape, dt_out); - - // Fill reference - library->fill_tensor_uniform(ref_src1, 0); - library->fill_tensor_uniform(ref_src2, 1); - - // Compute reference - ReferenceCPP::pixel_wise_multiplication(ref_src1, ref_src2, ref_dst, scale, convert_policy, rounding_policy); - - return ref_dst; -} - -RawTensor Reference::compute_reference_fixed_point_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, int fixed_point_position, - ConvertPolicy convert_policy, RoundingPolicy rounding_policy) -{ - // Create reference - RawTensor ref_src1(shape, dt_in0, 1, fixed_point_position); - RawTensor ref_src2(shape, dt_in1, 1, fixed_point_position); - RawTensor ref_dst(shape, dt_out, 1, fixed_point_position); - - // Fill reference - library->fill_tensor_uniform(ref_src1, 0); - library->fill_tensor_uniform(ref_src2, 1); - - // Compute reference - ReferenceCPP::fixed_point_pixel_wise_multiplication(ref_src1, ref_src2, ref_dst, scale, convert_policy, rounding_policy); - - return ref_dst; -} - -template <typename T> -RawTensor Reference::compute_reference_table_lookup(const TensorShape &shape, DataType dt_inout, std::map<T, T> &lut) -{ - // Create reference - RawTensor ref_src(shape, dt_inout); - RawTensor ref_dst(shape, dt_inout); - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::table_lookup(ref_src, ref_dst, lut); - - return ref_dst; -} -template RawTensor arm_compute::test::validation::Reference::compute_reference_table_lookup<uint8_t>(const TensorShape &shape, DataType dt_inout, std::map<uint8_t, uint8_t> &lut); -template RawTensor arm_compute::test::validation::Reference::compute_reference_table_lookup<int16_t>(const TensorShape &shape, DataType dt_inout, std::map<int16_t, int16_t> &lut); - -RawTensor Reference::compute_reference_threshold(const TensorShape &shape, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::U8); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::threshold(ref_src, ref_dst, threshold, false_value, true_value, type, upper); - - return ref_dst; -} - -RawTensor Reference::compute_reference_warp_perspective(const TensorShape &shape, RawTensor &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, - uint8_t constant_border_value) -{ - // Create reference - RawTensor ref_src(shape, DataType::U8); - RawTensor ref_dst(shape, DataType::U8); - - // Fill reference - library->fill_tensor_uniform(ref_src, 0); - - // Compute reference - ReferenceCPP::warp_perspective(ref_src, ref_dst, valid_mask, matrix, policy, border_mode, constant_border_value); - - return ref_dst; -} - -RawTensor Reference::compute_reference_batch_normalization_layer(const TensorShape &shape0, const TensorShape &shape1, DataType dt, float epsilon, int fixed_point_position) -{ - // Create reference - RawTensor ref_src(shape0, dt, 1, fixed_point_position); - RawTensor ref_dst(shape0, dt, 1, fixed_point_position); - RawTensor ref_mean(shape1, dt, 1, fixed_point_position); - RawTensor ref_var(shape1, dt, 1, fixed_point_position); - RawTensor ref_beta(shape1, dt, 1, fixed_point_position); - RawTensor ref_gamma(shape1, dt, 1, fixed_point_position); - - // Fill tensors - switch(dt) - { - case DataType::QS8: - { - const std::pair<int8_t, int8_t> bounds = get_batchnormalization_layer_test_bounds<int8_t>(fixed_point_position); - std::uniform_int_distribution<> distribution(bounds.first, bounds.second); - std::uniform_int_distribution<> distribution_var(0, bounds.second); - fill_tensors(distribution, { 0, 1, 3, 4 }, &ref_src, &ref_mean, &ref_beta, &ref_gamma); - fill_tensors(distribution_var, { 0 }, &ref_var); - break; - } - case DataType::QS16: - { - const std::pair<int16_t, int16_t> bounds = get_batchnormalization_layer_test_bounds<int16_t>(fixed_point_position); - std::uniform_int_distribution<> distribution(bounds.first, bounds.second); - std::uniform_int_distribution<> distribution_var(0, bounds.second); - fill_tensors(distribution, { 0, 1, 3, 4 }, &ref_src, &ref_mean, &ref_beta, &ref_gamma); - fill_tensors(distribution_var, { 0 }, &ref_var); - break; - } - case DataType::F16: - { - const std::pair<half_float::half, half_float::half> bounds = get_batchnormalization_layer_test_bounds<half_float::half>(); - std::uniform_real_distribution<> distribution(bounds.first, bounds.second); - std::uniform_real_distribution<> distribution_var(0, bounds.second); - fill_tensors(distribution, { 0, 1, 3, 4 }, &ref_src, &ref_mean, &ref_beta, &ref_gamma); - fill_tensors(distribution_var, { 0 }, &ref_var); - break; - } - case DataType::F32: - { - const std::pair<float, float> bounds = get_batchnormalization_layer_test_bounds<float>(); - std::uniform_real_distribution<> distribution(bounds.first, bounds.second); - std::uniform_real_distribution<> distribution_var(0, bounds.second); - fill_tensors(distribution, { 0, 1, 3, 4 }, &ref_src, &ref_mean, &ref_beta, &ref_gamma); - fill_tensors(distribution_var, { 0 }, &ref_var); - break; - } - default: - { - ARM_COMPUTE_ERROR("Not supported"); - break; - } - } - - // Compute reference - ReferenceCPP::batch_normalization_layer(ref_src, ref_dst, ref_mean, ref_var, ref_beta, ref_gamma, epsilon, fixed_point_position); - - return ref_dst; -} - -RawTensor Reference::compute_reference_roi_pooling_layer(const TensorShape &shape, DataType dt, const std::vector<ROI> &rois, const ROIPoolingLayerInfo &pool_info) -{ - TensorShape shape_dst; - shape_dst.set(0, pool_info.pooled_width()); - shape_dst.set(1, pool_info.pooled_height()); - shape_dst.set(2, shape.z()); - shape_dst.set(3, rois.size()); - - // Create reference - RawTensor ref_src(shape, dt); - RawTensor ref_dst(shape_dst, dt); - - // Fill reference - std::uniform_real_distribution<> distribution(-1, 1); - library->fill(ref_src, distribution, 0.0); - - // Compute reference - ReferenceCPP::roi_pooling_layer(ref_src, ref_dst, rois, pool_info); - - return ref_dst; -} - -RawTensor Reference::compute_reference_fixed_point_operation(const TensorShape &shape, DataType dt_in, DataType dt_out, FixedPointOp op, int fixed_point_position) -{ - // Create reference - RawTensor ref_src(shape, dt_in, 1, fixed_point_position); - RawTensor ref_dst(shape, dt_out, 1, fixed_point_position); - - // Fill reference - int min = 0; - int max = 0; - switch(op) - { - case(FixedPointOp::INV_SQRT): - min = 1; - max = (dt_in == DataType::QS8) ? 0x7F : 0x7FFF; - break; - case(FixedPointOp::LOG): - min = (1 << (fixed_point_position - 1)); - max = (dt_in == DataType::QS8) ? 0x3F : 0x3FFF; - break; - case(FixedPointOp::EXP): - min = -(1 << (fixed_point_position - 1)); - max = (1 << (fixed_point_position - 1)); - break; - case(FixedPointOp::RECIPROCAL): - min = 15; - max = (dt_in == DataType::QS8) ? 0x7F : 0x7FFF; - break; - default: - ARM_COMPUTE_ERROR("Fixed point operation not supported"); - } - std::uniform_int_distribution<> distribution(min, max); - library->fill(ref_src, distribution, 0); - - // Compute reference - ReferenceCPP::fixed_point_operation(ref_src, ref_dst, op); - - return ref_dst; -} - -} // namespace validation -} // namespace test -} // namespace arm_compute -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/Reference.h b/tests/validation/Reference.h deleted file mode 100644 index 698b60e96b..0000000000 --- a/tests/validation/Reference.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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. - */ -#ifndef __ARM_COMPUTE_TEST_REFERENCE_REFERENCE_H__ -#define __ARM_COMPUTE_TEST_REFERENCE_REFERENCE_H__ - -#include "RawTensor.h" -#include "Types.h" -#include "arm_compute/runtime/Array.h" - -#include <map> -#include <vector> - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -/** Interface for reference implementations. */ -class Reference -{ -public: - /** Compute reference sobel 3x3. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode Border mode to use for input tensor - * @param[in] constant_border_value Constant value to use if @p border_mode is constant - * - * @return Computed raw tensors along x and y axis. - */ - static std::pair<RawTensor, RawTensor> compute_reference_sobel_3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value); - /** Compute reference sobel 5x5. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode Border mode to use for input tensor - * @param[in] constant_border_value Constant value to use if @p border_mode is constant - * - * @return Computed raw tensors along x and y axis. - */ - static std::pair<RawTensor, RawTensor> compute_reference_sobel_5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value); - /** Compute reference Harris corners. - * - * @param[in] shape Shape of input tensor - * @param[in] threshold Minimum threshold with which to eliminate Harris Corner scores (computed using the normalized Sobel kernel). - * @param[in] min_dist Radial Euclidean distance for the euclidean distance stage - * @param[in] sensitivity Sensitivity threshold k from the Harris-Stephens equation - * @param[in] gradient_size The gradient window size to use on the input. The implementation supports 3, 5, and 7 - * @param[in] block_size The block window size used to compute the Harris Corner score. The implementation supports 3, 5, and 7. - * @param[in] border_mode Border mode to use - * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT. - * - * @return Computed corners' keypoints. - */ - static KeyPointArray compute_reference_harris_corners(const TensorShape &shape, float threshold, float min_dist, float sensitivity, - int32_t gradient_size, int32_t block_size, BorderMode border_mode, uint8_t constant_border_value); - /** Compute min max location. - * - * @param[in] shape Shape of the input tensors. - * @param[in] dt_in Data type of input tensor. - * @param[out] min Minimum value of tensor - * @param[out] max Maximum value of tensor - * @param[out] min_loc Array with locations of minimum values - * @param[out] max_loc Array with locations of maximum values - * @param[out] min_count Number of minimum values found - * @param[out] max_count Number of maximum values found - * - * @return Computed minimum, maximum values and their locations. - */ - static void compute_reference_min_max_location(const TensorShape &shape, DataType dt_in, void *min, void *max, IArray<Coordinates2D> &min_loc, IArray<Coordinates2D> &max_loc, - uint32_t &min_count, - uint32_t &max_count); - /** Compute reference integral image. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_integral_image(const TensorShape &shape); - /** Compute reference absolute difference. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_absolute_difference(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out); - /** Compute reference accumulate. - * - * @param[in] shape Shape of the input and output tensors. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_accumulate(const TensorShape &shape); - /** Compute reference accumulate. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] shift A uint32_t value within the range of [0, 15] - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_accumulate_squared(const TensorShape &shape, uint32_t shift); - /** Compute reference accumulate. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] alpha A float value within the range of [0, 1] - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_accumulate_weighted(const TensorShape &shape, float alpha); - /** Compute reference arithmetic addition. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] convert_policy Overflow policy of the operation. - * @param[in] fixed_point_position (Optional) Number of bits for the fractional part of the fixed point numbers - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_arithmetic_addition(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy convert_policy, int fixed_point_position = 0); - /** Compute reference arithmetic subtraction. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] convert_policy Overflow policy of the operation. - * @param[in] fixed_point_position (Optional) Number of bits for the fractional part of the fixed point numbers - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_arithmetic_subtraction(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy convert_policy, int fixed_point_position = 0); - /** Compute reference box3x3 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor. - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_box3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value); - /** Compute reference depth convert. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in Data type of input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] policy Overflow policy of the operation. - * @param[in] shift Value for down/up conversions. Must be 0 <= shift < 8. - * @param[in] fixed_point_position_in (Optional) Fixed point position for the input tensor. - * @param[in] fixed_point_position_out (Optional) Fixed point position for the output tensor. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_depth_convert(const TensorShape &shape, DataType dt_in, DataType dt_out, ConvertPolicy policy, - uint32_t shift, uint32_t fixed_point_position_in = 0, uint32_t fixed_point_position_out = 0); - /** Compute reference gaussian3x3 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_gaussian3x3(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value); - /** Compute reference gaussian5x5 filter. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] border_mode BorderMode used by the input tensor. - * @param[in] constant_border_value Constant to use if @p border_mode == CONSTANT. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_gaussian5x5(const TensorShape &shape, BorderMode border_mode, uint8_t constant_border_value); - /** Compute reference non linear filter function - * - * @param[in] shape Shape of the input and output tensors.Data type supported: U8 - * @param[in] function Non linear function to perform - * @param[in] mask_size Mask size. Supported sizes: 3, 5 - * @param[in] pattern Matrix pattern - * @param[in] mask The given mask. Will be used only if pattern is specified to PATTERN_OTHER - * @param[in] border_mode Strategy to use for borders. - * @param[in] constant_border_value (Optional) Constant value to use for borders if border_mode is set to CONSTANT. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_non_linear_filter(const TensorShape &shape, NonLinearFilterFunction function, unsigned int mask_size, - MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode, uint8_t constant_border_value = 0); - /** Compute reference pixel-wise multiplication - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] scale Non-negative scale. - * @param[in] convert_policy Overflow policy of the operation. - * @param[in] rounding_policy Rounding policy of the operation. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, ConvertPolicy convert_policy, - RoundingPolicy rounding_policy); - /** Compute reference pixel-wise multiplication. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in0 Data type of first input tensor. - * @param[in] dt_in1 Data type of second input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] scale Scale to apply after multiplication. Must be positive. - * @param[in] fixed_point_position Fixed point position that expresses the number of bits for the fractional part of the number. - * @param[in] convert_policy Overflow policy of the operation. - * @param[in] rounding_policy Rounding policy of the operation. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_fixed_point_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, int fixed_point_position, - ConvertPolicy convert_policy, RoundingPolicy rounding_policy); - /** Compute reference Table Lookup. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_inout Data type of input/output tensor. - * @param[in] lut Input lookup table. - * - * @return Computed raw tensor. - */ - template <typename T> - static RawTensor compute_reference_table_lookup(const TensorShape &shape, DataType dt_inout, std::map<T, T> &lut); - /** Compute reference threshold. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] threshold Threshold. When the threshold type is RANGE, this is used as the lower threshold. - * @param[in] false_value value to set when the condition is not respected. - * @param[in] true_value value to set when the condition is respected. - * @param[in] type Thresholding type. Either RANGE or BINARY. - * @param[in] upper Upper threshold. Only used when the thresholding type is RANGE. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_threshold(const TensorShape &shape, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper); - - /** Compute reference Warp Perspective. - * - * @param[in] shape Shape of the input and output tensors. - * @param[out] valid_mask Valid mask tensor. - * @param[in] matrix The perspective matrix. Must be 3x3 of type float. - * @param[in] policy The interpolation type. - * @param[in] border_mode Strategy to use for borders. - * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_warp_perspective(const TensorShape &shape, RawTensor &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, - uint8_t constant_border_value); - - /** Compute reference batch normalization layer. - * - * @param[in] shape0 Shape of the input and output tensors. - * @param[in] shape1 Shape of the vector tensors. - * @param[in] dt Data type of all input and output tensors. - * @param[in] epsilon Small value to avoid division with zero. - * @param[in] fixed_point_position Fixed point position. - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_batch_normalization_layer(const TensorShape &shape0, const TensorShape &shape1, DataType dt, float epsilon, int fixed_point_position = 0); - /** Compute reference roi pooling layer. - * - * @param[in] shape Shape of the input tensor. - * @param[in] dt Data type of input and output tensors. - * @param[in] rois Region of interest vector. - * @param[in] pool_info ROI Pooling Layer information. - */ - static RawTensor compute_reference_roi_pooling_layer(const TensorShape &shape, DataType dt, const std::vector<ROI> &rois, const ROIPoolingLayerInfo &pool_info); - /** Compute reference fixed point operation. - * - * @param[in] shape Shape of the input and output tensors. - * @param[in] dt_in Data type of the input tensor. - * @param[in] dt_out Data type of the output tensor. - * @param[in] op Fixed point operation to perform. - * @param[in] fixed_point_position Number of bits for the fractional part of the fixed point numbers - * - * @return Computed raw tensor. - */ - static RawTensor compute_reference_fixed_point_operation(const TensorShape &shape, DataType dt_in, DataType dt_out, FixedPointOp op, int fixed_point_position); - -protected: - Reference() = default; - ~Reference() = default; -}; -} // namespace validation -} // namespace test -} // namespace arm_compute -#endif /* __ARM_COMPUTE_TEST_REFERENCE_REFERENCE_H__ */ diff --git a/tests/validation/ReferenceCPP.cpp b/tests/validation/ReferenceCPP.cpp deleted file mode 100644 index 029f6586f5..0000000000 --- a/tests/validation/ReferenceCPP.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * 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 "ReferenceCPP.h" - -#include "TensorFactory.h" -#include "TensorOperations.h" -#include "TensorVisitors.h" -#include "TypePrinter.h" - -#include "arm_compute/core/Coordinates.h" -#include "arm_compute/core/Error.h" -#include "arm_compute/core/TensorInfo.h" -#include "arm_compute/core/TensorShape.h" -#include "arm_compute/runtime/Tensor.h" - -#include "boost_wrapper.h" - -#include <algorithm> -#include <functional> -#include <memory> -#include <numeric> -#include <vector> - -using namespace arm_compute::test::validation::tensor_visitors; - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -// Sobel 3x3 -void ReferenceCPP::sobel_3x3(RawTensor &src, RawTensor &dst_x, RawTensor &dst_y, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst_x.data_type() != DataType::S16 || dst_y.data_type() != DataType::S16); - Tensor<uint8_t> s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast<const uint8_t *>(src.data())); - Tensor<int16_t> dx(dst_x.shape(), dst_x.data_type(), dst_x.fixed_point_position(), reinterpret_cast<int16_t *>(dst_x.data())); - Tensor<int16_t> dy(dst_y.shape(), dst_y.data_type(), dst_y.fixed_point_position(), reinterpret_cast<int16_t *>(dst_y.data())); - tensor_operations::sobel_3x3(s, dx, dy, border_mode, constant_border_value); -} - -// Sobel 5x5 -void ReferenceCPP::sobel_5x5(RawTensor &src, RawTensor &dst_x, RawTensor &dst_y, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst_x.data_type() != DataType::S16 || dst_y.data_type() != DataType::S16); - Tensor<uint8_t> s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast<const uint8_t *>(src.data())); - Tensor<int16_t> dx(dst_x.shape(), dst_x.data_type(), dst_x.fixed_point_position(), reinterpret_cast<int16_t *>(dst_x.data())); - Tensor<int16_t> dy(dst_y.shape(), dst_y.data_type(), dst_y.fixed_point_position(), reinterpret_cast<int16_t *>(dst_y.data())); - tensor_operations::sobel_5x5(s, dx, dy, border_mode, constant_border_value); -} - -// Harris corners -void ReferenceCPP::harris_corners(RawTensor &src, RawTensor &Gx, RawTensor &Gy, const RawTensor &candidates, const RawTensor &non_maxima, float threshold, float min_dist, float sensitivity, - int32_t gradient_size, int32_t block_size, KeyPointArray &corners, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || (Gx.data_type() != DataType::S16 && Gx.data_type() != DataType::S32) || (Gy.data_type() != DataType::S16 && Gy.data_type() != DataType::S32) - || candidates.data_type() != DataType::F32 || non_maxima.data_type() != DataType::F32); - - Tensor<uint8_t> s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast<const uint8_t *>(src.data())); - Tensor<float> c(candidates.shape(), candidates.data_type(), candidates.fixed_point_position(), const_cast<float *>(reinterpret_cast<const float *>(candidates.data()))); // NOLINT - Tensor<float> nm(non_maxima.shape(), non_maxima.data_type(), non_maxima.fixed_point_position(), const_cast<float *>(reinterpret_cast<const float *>(non_maxima.data()))); // NOLINT - - if(gradient_size == 7) - { - Tensor<int32_t> gx(Gx.shape(), Gx.data_type(), Gx.fixed_point_position(), reinterpret_cast<int32_t *>(Gx.data())); - Tensor<int32_t> gy(Gy.shape(), Gy.data_type(), Gy.fixed_point_position(), reinterpret_cast<int32_t *>(Gy.data())); - tensor_operations::harris_corners(s, gx, gy, c, nm, threshold, min_dist, sensitivity, gradient_size, block_size, corners, border_mode, constant_border_value); - } - else - { - Tensor<int16_t> gx(Gx.shape(), Gx.data_type(), Gx.fixed_point_position(), reinterpret_cast<int16_t *>(Gx.data())); - Tensor<int16_t> gy(Gy.shape(), Gy.data_type(), Gy.fixed_point_position(), reinterpret_cast<int16_t *>(Gy.data())); - tensor_operations::harris_corners(s, gx, gy, c, nm, threshold, min_dist, sensitivity, gradient_size, block_size, corners, border_mode, constant_border_value); - } -} - -// Minimum maximum location -void ReferenceCPP::min_max_location(const RawTensor &src, void *min, void *max, IArray<Coordinates2D> &min_loc, IArray<Coordinates2D> &max_loc, uint32_t &min_count, uint32_t &max_count) -{ - const TensorVariant s = TensorFactory::get_tensor(src); - boost::apply_visitor(tensor_visitors::min_max_location_visitor(min, max, min_loc, max_loc, min_count, max_count), s); -} - -// Absolute difference -void ReferenceCPP::absolute_difference(const RawTensor &src1, const RawTensor &src2, RawTensor &dst) -{ - const TensorVariant s1 = TensorFactory::get_tensor(src1); - const TensorVariant s2 = TensorFactory::get_tensor(src2); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(absolute_difference_visitor(), s1, s2, d); -} - -// Integral image -void ReferenceCPP::integral_image(const RawTensor &src, RawTensor &dst) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.data_type() != DataType::U32); - const Tensor<uint8_t> s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast<const uint8_t *>(src.data())); - 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) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.data_type() != DataType::S16); - const Tensor<uint8_t> s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast<const uint8_t *>(src.data())); - Tensor<int16_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<int16_t *>(dst.data())); - tensor_operations::accumulate(s, d); -} - -// Accumulate squared -void ReferenceCPP::accumulate_squared(const RawTensor &src, RawTensor &dst, uint32_t shift) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.data_type() != DataType::S16); - const Tensor<uint8_t> s(src.shape(), src.data_type(), src.fixed_point_position(), reinterpret_cast<const uint8_t *>(src.data())); - Tensor<int16_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<int16_t *>(dst.data())); - tensor_operations::accumulate_squared(s, d, shift); -} - -// Accumulate weighted -void ReferenceCPP::accumulate_weighted(const RawTensor &src, RawTensor &dst, float alpha) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.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<uint8_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<uint8_t *>(dst.data())); - tensor_operations::accumulate_weighted(s, d, alpha); -} - -// Arithmetic addition -void ReferenceCPP::arithmetic_addition(const RawTensor &src1, const RawTensor &src2, RawTensor &dst, ConvertPolicy convert_policy) -{ - const TensorVariant s1 = TensorFactory::get_tensor(src1); - const TensorVariant s2 = TensorFactory::get_tensor(src2); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(arithmetic_addition_visitor(convert_policy), s1, s2, d); -} - -// Arithmetic subtraction -void ReferenceCPP::arithmetic_subtraction(const RawTensor &src1, const RawTensor &src2, RawTensor &dst, ConvertPolicy convert_policy) -{ - const TensorVariant s1 = TensorFactory::get_tensor(src1); - const TensorVariant s2 = TensorFactory::get_tensor(src2); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(arithmetic_subtraction_visitor(convert_policy), s1, s2, d); -} - -// Box3x3 filter -void ReferenceCPP::box3x3(const RawTensor &src, RawTensor &dst, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.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<uint8_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<uint8_t *>(dst.data())); - tensor_operations::box3x3(s, d, border_mode, constant_border_value); -} - -// Depth conversion -void ReferenceCPP::depth_convert(const RawTensor &src, RawTensor &dst, ConvertPolicy policy, uint32_t shift) -{ - const TensorVariant s = TensorFactory::get_tensor(src); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(tensor_visitors::depth_convert_visitor(policy, shift), s, d); -} - -// Gaussian3x3 filter -void ReferenceCPP::gaussian3x3(const RawTensor &src, RawTensor &dst, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.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<uint8_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<uint8_t *>(dst.data())); - tensor_operations::gaussian3x3(s, d, border_mode, constant_border_value); -} - -// Gaussian5x5 filter -void ReferenceCPP::gaussian5x5(const RawTensor &src, RawTensor &dst, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.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<uint8_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<uint8_t *>(dst.data())); - tensor_operations::gaussian5x5(s, d, border_mode, constant_border_value); -} - -// Non linear filter -void ReferenceCPP::non_linear_filter(const RawTensor &src, RawTensor &dst, NonLinearFilterFunction function, unsigned int mask_size, - MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.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<uint8_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<uint8_t *>(dst.data())); - tensor_operations::non_linear_filter(s, d, function, mask_size, pattern, mask, border_mode, constant_border_value); -} - -// Pixel-wise multiplication -void ReferenceCPP::pixel_wise_multiplication(const RawTensor &src1, const RawTensor &src2, RawTensor &dst, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy) -{ - const TensorVariant s1 = TensorFactory::get_tensor(src1); - const TensorVariant s2 = TensorFactory::get_tensor(src2); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(pixel_wise_multiplication_visitor(scale, convert_policy, rounding_policy), s1, s2, d); -} - -// Fixed-point Pixel-wise multiplication -void ReferenceCPP::fixed_point_pixel_wise_multiplication(const RawTensor &src1, const RawTensor &src2, RawTensor &dst, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy) -{ - const TensorVariant s1 = TensorFactory::get_tensor(src1); - const TensorVariant s2 = TensorFactory::get_tensor(src2); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(tensor_visitors::fixed_point_pixel_wise_multiplication_visitor(s1, s2, scale, convert_policy, rounding_policy), d); -} - -// Table lookup -template <typename T> -void ReferenceCPP::table_lookup(const RawTensor &src, RawTensor &dst, std::map<T, T> &lut) -{ - const TensorVariant s = TensorFactory::get_tensor(src); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(tensor_visitors::table_lookup<T>(s, lut), d); -} -#ifndef DOXYGEN_SKIP_THIS -template void arm_compute::test::validation::ReferenceCPP::table_lookup<uint8_t>(const RawTensor &src, RawTensor &dst, std::map<uint8_t, uint8_t> &lut); -template void arm_compute::test::validation::ReferenceCPP::table_lookup<int16_t>(const RawTensor &src, RawTensor &dst, std::map<int16_t, int16_t> &lut); -#endif /* DOXYGEN_SKIP_THIS */ - -// Threshold -void ReferenceCPP::threshold(const RawTensor &src, RawTensor &dst, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.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<uint8_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<uint8_t *>(dst.data())); - tensor_operations::threshold(s, d, threshold, false_value, true_value, type, upper); -} - -// Warp perspective -void ReferenceCPP::warp_perspective(const RawTensor &src, RawTensor &dst, RawTensor &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(src.data_type() != DataType::U8 || dst.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<uint8_t> d(dst.shape(), dst.data_type(), dst.fixed_point_position(), reinterpret_cast<uint8_t *>(dst.data())); - Tensor<uint8_t> vmask(valid_mask.shape(), valid_mask.data_type(), valid_mask.fixed_point_position(), reinterpret_cast<uint8_t *>(valid_mask.data())); - tensor_operations::warp_perspective(s, d, vmask, matrix, policy, border_mode, constant_border_value); -} - -// Batch Normalization Layer -void ReferenceCPP::batch_normalization_layer(const RawTensor &src, RawTensor &dst, const RawTensor &mean, const RawTensor &var, const RawTensor &beta, const RawTensor &gamma, float epsilon, - int fixed_point_position) -{ - const TensorVariant s = TensorFactory::get_tensor(src); - TensorVariant d = TensorFactory::get_tensor(dst); - const TensorVariant m = TensorFactory::get_tensor(mean); - const TensorVariant v = TensorFactory::get_tensor(var); - const TensorVariant b = TensorFactory::get_tensor(beta); - const TensorVariant g = TensorFactory::get_tensor(gamma); - boost::apply_visitor(tensor_visitors::batch_normalization_layer_visitor(s, m, v, b, g, epsilon, fixed_point_position), d); -} - -// ROI Pooling Layer -void ReferenceCPP::roi_pooling_layer(const RawTensor &src, RawTensor &dst, const std::vector<ROI> &rois, const ROIPoolingLayerInfo &pool_info) -{ - const TensorVariant s = TensorFactory::get_tensor(src); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(tensor_visitors::roi_pooling_layer_visitor(s, rois, pool_info), d); -} - -// Fixed point operation -void ReferenceCPP::fixed_point_operation(const RawTensor &src, RawTensor &dst, FixedPointOp op) -{ - const TensorVariant s = TensorFactory::get_tensor(src); - TensorVariant d = TensorFactory::get_tensor(dst); - boost::apply_visitor(tensor_visitors::fixed_point_operation_visitor(s, op), d); -} - -} // namespace validation -} // namespace test -} // namespace arm_compute diff --git a/tests/validation/ReferenceCPP.h b/tests/validation/ReferenceCPP.h deleted file mode 100644 index fcc4da471d..0000000000 --- a/tests/validation/ReferenceCPP.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - * 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. - */ -#ifndef __ARM_COMPUTE_TEST_REFERENCE_REFERENCE_CPP_H__ -#define __ARM_COMPUTE_TEST_REFERENCE_REFERENCE_CPP_H__ - -#include "RawTensor.h" -#include "Reference.h" - -#include <map> -#include <memory> -#include <ostream> -#include <vector> - -namespace arm_compute -{ -class Tensor; - -namespace test -{ -namespace validation -{ -/** C++ reference implementation. */ -class ReferenceCPP final : public Reference -{ -public: - /** Function to compute reference sobel 3x3. - * - * @param[in] src Input tensor. - * @param[in] dst_x Result tensor along x axis - * @param[in] dst_y Result tensor along y axis - * @param[in] border_mode Border mode to use for input tensor - * @param[in] constant_border_value Constant value to use if @p border_mode is constant - * - */ - static void sobel_3x3(RawTensor &src, RawTensor &dst_x, RawTensor &dst_y, BorderMode border_mode, uint8_t constant_border_value); - /** Function to compute reference sobel 5x5. - * - * @param[in] src Input tensor. - * @param[in] dst_x Result tensor along x axis - * @param[in] dst_y Result tensor along y axis - * @param[in] border_mode Border mode to use for input tensor - * @param[in] constant_border_value Constant value to use if @p border_mode is constant - * - */ - static void sobel_5x5(RawTensor &src, RawTensor &dst_x, RawTensor &dst_y, BorderMode border_mode, uint8_t constant_border_value); - /** Function to compute reference Harris corners. - * - * @param[in] src Input tensor - * @param[in] Gx Tensor used to compute Sobel along the x axis - * @param[in] Gy Tensor used to compute Sobel along the y axis - * @param[in] candidates Tensor used to store candidate corners - * @param[in] non_maxima Tensor used to store non_maxima suppressed candidate corners - * @param[in] threshold Minimum threshold with which to eliminate Harris Corner scores (computed using the normalized Sobel kernel). - * @param[in] min_dist Radial Euclidean distance for the euclidean distance stage - * @param[in] sensitivity Sensitivity threshold k from the Harris-Stephens equation - * @param[in] gradient_size The gradient window size to use on the input. The implementation supports 3, 5, and 7 - * @param[in] block_size The block window size used to compute the Harris Corner score. The implementation supports 3, 5, and 7. - * @param[out] corners Array of keypoints to store the results. - * @param[in] border_mode Border mode to use - * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT. - * - */ - static void harris_corners(RawTensor &src, RawTensor &Gx, RawTensor &Gy, const RawTensor &candidates, const RawTensor &non_maxima, float threshold, float min_dist, float sensitivity, - int32_t gradient_size, int32_t block_size, KeyPointArray &corners, BorderMode border_mode, uint8_t constant_border_value); - /** Function to compute the min max values and their location in a tensor. - * - * @param[in] src Input tensor. - * @param[out] min Minimum value of the tensor. - * @param[out] max Maximum value of the tensor - * @param[out] min_loc Array with locations of minimum values - * @param[out] max_loc Array with locations of maximum values - * @param[out] min_count Number of minimum values found - * @param[out] max_count Number of maximum values found - */ - static void min_max_location(const RawTensor &src, void *min, void *max, IArray<Coordinates2D> &min_loc, IArray<Coordinates2D> &max_loc, uint32_t &min_count, uint32_t &max_count); - /** Function to compute the integral image of a tensor. - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - */ - static void integral_image(const RawTensor &src, RawTensor &dst); - /** Function to compute the absolute difference between two tensors. - * - * @param[in] src1 First tensor. - * @param[in] src2 Second tensor. - * @param[out] dst Result tensor. - */ - static void absolute_difference(const RawTensor &src1, const RawTensor &src2, RawTensor &dst); - /** Function to accumulate an input tensor into an output tensor. - * - * @param[in] src Input tensor. - * @param[in, out] dst Result tensor. - */ - static void accumulate(const RawTensor &src, RawTensor &dst); - /** Function to accumulate a squared value from an input tensor to an output tensor. - * - * @param[in] src Input tensor. - * @param[in, out] dst Result tensor. - * @param[in] shift A uint32_t value within the range of [0, 15] - */ - static void accumulate_squared(const RawTensor &src, RawTensor &dst, uint32_t shift); - /** Function to accumulate a weighted value from an input tensor to an output tensor. - * - * @param[in] src Input tensor. - * @param[in, out] dst Result tensor. - * @param[in] alpha A float value within the range of [0, 1] - */ - static void accumulate_weighted(const RawTensor &src, RawTensor &dst, float alpha); - /** Arithmetic addition of @p src1 and @p src2 - * - * @param[in] src1 First tensor. - * @param[in] src2 Second tensor. - * @param[out] dst Result tensor. - * @param[in] convert_policy Overflow policy. - */ - static void arithmetic_addition(const RawTensor &src1, const RawTensor &src2, RawTensor &dst, ConvertPolicy convert_policy); - /** Arithmetic subtraction of @p src2 from @p src1 - * - * @param[in] src1 First tensor. - * @param[in] src2 Second tensor. - * @param[out] dst Result tensor. - * @param[in] convert_policy Overflow policy. - */ - static void arithmetic_subtraction(const RawTensor &src1, const RawTensor &src2, RawTensor &dst, ConvertPolicy convert_policy); - /** Function to compute box3x3 filtered result tensor. - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - * @param[in] border_mode Border mode. - * @param[in] constant_border_value Constant border value if @p border_mode is BorderMode::CONSTANT. - */ - static void box3x3(const RawTensor &src, RawTensor &dst, BorderMode border_mode, uint8_t constant_border_value); - /** Depth conversion from @p src to @p dst - * - * @param[in] src First tensor. - * @param[out] dst Result tensor. - * @param[in] policy Overflow policy. - * @param[in] shift Value for down/up conversions. - */ - static void depth_convert(const RawTensor &src, RawTensor &dst, ConvertPolicy policy, uint32_t shift); - /** Function to compute gaussian3x3 filtered result tensor. - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - * @param[in] border_mode Border mode - * @param[in] constant_border_value Constant border value if @p border_mode is BorderMode::CONSTANT - */ - static void gaussian3x3(const RawTensor &src, RawTensor &dst, BorderMode border_mode, uint8_t constant_border_value); - /** Function to compute gaussian5x5 filtered result tensor. - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - * @param[in] border_mode Border mode - * @param[in] constant_border_value Constant border value if @p border_mode is BorderMode::CONSTANT - */ - static void gaussian5x5(const RawTensor &src, RawTensor &dst, BorderMode border_mode, uint8_t constant_border_value); - /** Compute non linear filter function. - * - * @param[in] src First input tensor - * @param[out] dst Output tensor - * @param[in] function Non linear function to perform - * @param[in] mask_size Mask size. Supported sizes: 3, 5 - * @param[in] pattern Matrix pattern - * @param[in] mask The given mask. - * @param[in] border_mode Strategy to use for borders. - * @param[in] constant_border_value (Optional) Constant value to use for borders if border_mode is set to CONSTANT. - */ - static void non_linear_filter(const RawTensor &src, RawTensor &dst, NonLinearFilterFunction function, unsigned int mask_size, - MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode, uint8_t constant_border_value = 0); - /** Element-wise multiplication of @p src1, @p src2 and @p scale - * - * @param[in] src1 First tensor. - * @param[in] src2 Second tensor. - * @param[out] dst Result tensor. - * @param[in] scale A non-negative float multiplied to each product. - * @param[in] convert_policy Overflow policy. - * @param[in] rounding_policy Rounding policy. - */ - static void pixel_wise_multiplication(const RawTensor &src1, const RawTensor &src2, RawTensor &dst, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy); - /** Fixed-point Pixel-wise multiplication of @p src1 by @p src2 - * - * @param[in] src1 First tensor. - * @param[in] src2 Second tensor. - * @param[out] dst Result tensor. - * @param[in] scale A non-negative float multiplied to each product. - * @param[in] convert_policy Overflow policy. - * @param[in] rounding_policy Rounding policy. - */ - static void fixed_point_pixel_wise_multiplication(const RawTensor &src1, const RawTensor &src2, RawTensor &dst, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy); - /** Table Lookup f@p src to @p dst - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - * @param[in] lut Input lookup table. - */ - template <typename T> - static void table_lookup(const RawTensor &src, RawTensor &dst, std::map<T, T> &lut); - /** Threshold of@p src to @p dst - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - * @param[in] threshold Threshold. When the threhold type is RANGE, this is used as the lower threshold. - * @param[in] false_value value to set when the condition is not respected. - * @param[in] true_value value to set when the condition is respected. - * @param[in] type Thresholding type. Either RANGE or BINARY. - * @param[in] upper Upper threshold. Only used when the thresholding type is RANGE. - */ - static void threshold(const RawTensor &src, RawTensor &dst, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper); - /** Warp perspective of@p src to @p dst - * - * @param[in] src First tensor. - * @param[out] dst Result tensor. - * @param[out] valid_mask Valid mask tensor. - * @param[in] matrix The perspective matrix. Must be 3x3 of type float. - * @param[in] policy The interpolation type. - * @param[in] border_mode Strategy to use for borders. - * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT. - */ - static void warp_perspective(const RawTensor &src, RawTensor &dst, RawTensor &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value); - - /** Batch Normalization of @p src based on the information from @p norm_info. - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - * @param[out] mean Mean vector tensor. - * @param[out] var Var vector tensor. - * @param[out] beta Beta vector tensor. - * @param[out] gamma Gamma vector tensor. - * @param[in] epsilon Small value to avoid division with zero. - * @param[in] fixed_point_position Fixed point position. - */ - static void batch_normalization_layer(const RawTensor &src, RawTensor &dst, const RawTensor &mean, const RawTensor &var, const RawTensor &beta, const RawTensor &gamma, float epsilon, - int fixed_point_position = 0); - /** ROI Pooling layer of @p src based on the information from @p pool_info and @p rois. - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - * @param[in] rois Region of Interest points. - * @param[in] pool_info ROI Pooling Layer information. - */ - static void roi_pooling_layer(const RawTensor &src, RawTensor &dst, const std::vector<ROI> &rois, const ROIPoolingLayerInfo &pool_info); - /** Fixed point operations of @p src - * - * @param[in] src Input tensor. - * @param[out] dst Result tensor. - * @param[in] op Fixed point operation to perform. - */ - static void fixed_point_operation(const RawTensor &src, RawTensor &dst, FixedPointOp op); - -private: - ReferenceCPP() = delete; - ~ReferenceCPP() = delete; -}; -} // namespace validation -} // namespace test -} // namespace arm_compute -#endif /* __ARM_COMPUTE_TEST_REFERENCE_REFERENCE_CPP_H__ */ diff --git a/tests/validation/Tensor.h b/tests/validation/Tensor.h deleted file mode 100644 index 84d76e7143..0000000000 --- a/tests/validation/Tensor.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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. - */ -#ifndef __ARM_COMPUTE_TEST_TENSOR_H__ -#define __ARM_COMPUTE_TEST_TENSOR_H__ - -#include "arm_compute/core/TensorShape.h" -#include "arm_compute/core/Types.h" - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -template <typename T> -class Tensor -{ -public: - Tensor() - : _shape(), _dt(DataType::UNKNOWN), _fixed_point_position(0), _ptr(nullptr), _ptr_const(nullptr) {}; - - Tensor(TensorShape shape, DataType dt, int fixed_point_position, T *ptr) - : _shape(shape), _dt(dt), _fixed_point_position(fixed_point_position), _ptr(ptr), _ptr_const(nullptr) {}; - - Tensor(TensorShape shape, DataType dt, int fixed_point_position, const T *ptr) - : _shape(shape), _dt(dt), _fixed_point_position(fixed_point_position), _ptr(nullptr), _ptr_const(ptr) {}; - - Tensor(const Tensor &tensor) = delete; - Tensor &operator=(const Tensor &) = delete; - Tensor(Tensor &&) = default; - Tensor &operator=(Tensor &&) = default; - - ~Tensor() = default; - - T &operator[](size_t offset) - { - ARM_COMPUTE_ERROR_ON(_ptr == nullptr); - - return _ptr[offset]; - } - - const T &operator[](size_t offset) const - { - const T *ptr = (_ptr_const != nullptr) ? _ptr_const : _ptr; - - ARM_COMPUTE_ERROR_ON(ptr == nullptr); - - return ptr[offset]; // NOLINT - } - - int num_elements() const - { - return std::accumulate(_shape.cbegin(), _shape.cend(), 1, std::multiplies<int>()); - } - - TensorShape shape() const - { - return _shape; - } - - DataType data_type() const - { - return _dt; - } - - int fixed_point_position() const - { - return _fixed_point_position; - } - - const T *data() const - { - return (_ptr_const != nullptr) ? _ptr_const : _ptr; - } - - T *data() - { - return _ptr; - } - - const T *data_const() const - { - return _ptr_const; - } - -private: - TensorShape _shape; - DataType _dt; - int _fixed_point_position; - T *_ptr; - const T *_ptr_const; -}; -} // namespace validation -} // test -} // arm_compute - -#endif /* __ARM_COMPUTE_TEST_TENSOR_H__ */ diff --git a/tests/validation/TensorFactory.h b/tests/validation/TensorFactory.h deleted file mode 100644 index a3bb5f9615..0000000000 --- a/tests/validation/TensorFactory.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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. - */ -#ifndef __ARM_COMPUTE_TEST_TENSOR_FACTORY_H__ -#define __ARM_COMPUTE_TEST_TENSOR_FACTORY_H__ - -#include "arm_compute/core/Error.h" -#include "tests/RawTensor.h" -#include "tests/validation/Tensor.h" -#include "tests/validation/half.h" - -#include "boost_wrapper.h" - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -using TensorVariant = boost::variant<Tensor<uint8_t>, Tensor<int8_t>, - Tensor<uint16_t>, Tensor<int16_t>, - Tensor<uint32_t>, Tensor<int32_t>, - Tensor<half_float::half>, - Tensor<float>>; - -/** Helper to create a constant type if the passed reference is constant. */ -template <typename R, typename T> -struct match_const -{ - using type = typename std::conditional<std::is_const<typename std::remove_reference<R>::type>::value, const T, T>::type; -}; - -class TensorFactory -{ -public: - template <typename R> - static TensorVariant get_tensor(R &&raw) - { - TensorVariant v; - DataType dt = raw.data_type(); - int fixed_point_position = raw.fixed_point_position(); - auto shape = raw.shape(); - auto data = raw.data(); - - switch(dt) - { - case DataType::U8: - using value_type_u8 = typename match_const<R, uint8_t>::type; - v = Tensor<uint8_t>(shape, dt, fixed_point_position, reinterpret_cast<value_type_u8 *>(data)); - break; - case DataType::S8: - case DataType::QS8: - using value_type_s8 = typename match_const<R, int8_t>::type; - v = Tensor<int8_t>(shape, dt, fixed_point_position, reinterpret_cast<value_type_s8 *>(data)); - break; - case DataType::U16: - using value_type_u16 = typename match_const<R, uint16_t>::type; - v = Tensor<uint16_t>(shape, dt, fixed_point_position, reinterpret_cast<value_type_u16 *>(data)); - break; - case DataType::S16: - case DataType::QS16: - using value_type_s16 = typename match_const<R, int16_t>::type; - v = Tensor<int16_t>(shape, dt, fixed_point_position, reinterpret_cast<value_type_s16 *>(data)); - break; - case DataType::U32: - using value_type_u32 = typename match_const<R, uint32_t>::type; - v = Tensor<uint32_t>(shape, dt, fixed_point_position, reinterpret_cast<value_type_u32 *>(data)); - break; - case DataType::S32: - using value_type_s32 = typename match_const<R, int32_t>::type; - v = Tensor<int32_t>(shape, dt, fixed_point_position, reinterpret_cast<value_type_s32 *>(data)); - break; - case DataType::F16: - using value_type_f16 = typename match_const<R, half_float::half>::type; - v = Tensor<half_float::half>(shape, dt, fixed_point_position, reinterpret_cast<value_type_f16 *>(data)); - break; - case DataType::F32: - using value_type_f32 = typename match_const<R, float>::type; - v = Tensor<float>(shape, dt, fixed_point_position, reinterpret_cast<value_type_f32 *>(data)); - break; - default: - ARM_COMPUTE_ERROR("NOT SUPPORTED!"); - } - return v; - } -}; -} // namespace validation -} // namespace test -} // namespace arm_compute - -#endif /* __ARM_COMPUTE_TEST_TENSOR_FACTORY_H__ */ diff --git a/tests/validation/TensorOperations.h b/tests/validation/TensorOperations.h deleted file mode 100644 index b9ffa49544..0000000000 --- a/tests/validation/TensorOperations.h +++ /dev/null @@ -1,1178 +0,0 @@ -/* - * 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. - */ -#ifndef __ARM_COMPUTE_TEST_TENSOR_OPERATIONS_H__ -#define __ARM_COMPUTE_TEST_TENSOR_OPERATIONS_H__ - -#include "arm_compute/core/FixedPoint.h" -#include "arm_compute/core/Helpers.h" -#include "arm_compute/core/Types.h" -#include "support/ToolchainSupport.h" -#include "tests/Types.h" -#include "tests/Utils.h" -#include "tests/validation/FixedPoint.h" -#include "tests/validation/Tensor.h" -#include "tests/validation/ValidationUserConfiguration.h" -#include "tests/validation/half.h" - -#include <algorithm> -#include <array> -#include <cmath> -#include <random> -#include <string> -#include <vector> - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -namespace tensor_operations -{ -namespace -{ -template <class T> -struct is_floating_point - : std::integral_constant < bool, - std::is_same<float, typename std::remove_cv<T>::type>::value || std::is_same<half_float::half, typename std::remove_cv<T>::type>::value - || std::is_same<double, typename std::remove_cv<T>::type>::value || std::is_same<long double, typename std::remove_cv<T>::type>::value > -{ -}; - -// Return a tensor element at a specified coordinate with different border modes -template <typename T> -T tensor_elem_at(const Tensor<T> &in, Coordinates coord, BorderMode border_mode, T constant_border_value) -{ - const int x = coord.x(); - const int y = coord.y(); - const int width = static_cast<int>(in.shape().x()); - const int height = static_cast<int>(in.shape().y()); - - // If coordinates beyond range of tensor's width or height - if(x < 0 || y < 0 || x >= width || y >= height) - { - if(border_mode == BorderMode::REPLICATE) - { - coord.set(0, std::max(0, std::min(x, width - 1))); - coord.set(1, std::max(0, std::min(y, height - 1))); - } - else - { - return constant_border_value; - } - } - - return in[coord2index(in.shape(), coord)]; -} - -/** Apply 2D spatial filter on a single element of @p in at coordinates @p coord - * - * - filter sizes have to be odd number - * - Row major order of filter assumed - * - TO_ZERO rounding policy assumed - * - SATURATE convert policy assumed - * - */ -template <typename T1, typename T2, typename T3> -void apply_2d_spatial_filter(Coordinates coord, const Tensor<T1> &in, Tensor<T3> &out, const TensorShape &filter_shape, const T2 *filter_itr, float scale, BorderMode border_mode, - T1 constant_border_value = 0) -{ - double val = 0; - const int x = coord.x(); - const int y = coord.y(); - for(int j = y - static_cast<int>(filter_shape[1] / 2); j <= y + static_cast<int>(filter_shape[1] / 2); ++j) - { - for(int i = x - static_cast<int>(filter_shape[0] / 2); i <= x + static_cast<int>(filter_shape[0] / 2); ++i) - { - coord.set(0, i); - coord.set(1, j); - val += static_cast<double>(*filter_itr) * tensor_elem_at(in, coord, border_mode, constant_border_value); - ++filter_itr; - } - } - coord.set(0, x); - coord.set(1, y); - const double rounded_val = support::cpp11::trunc(val * static_cast<double>(scale)); - out[coord2index(in.shape(), coord)] = saturate_cast<T3>(rounded_val); -} -} // namespace - -template <typename T> -T bilinear_policy(const Tensor<T> &in, Coordinates id, float xn, float yn, BorderMode border_mode, uint8_t constant_border_value) -{ - int idx = std::floor(xn); - int idy = std::floor(yn); - - const float dx = xn - idx; - const float dy = yn - idy; - const float dx_1 = 1.0f - dx; - const float dy_1 = 1.0f - dy; - - id.set(0, idx); - id.set(1, idy); - const T tl = tensor_elem_at(in, id, border_mode, constant_border_value); - id.set(0, idx + 1); - id.set(1, idy); - const T tr = tensor_elem_at(in, id, border_mode, constant_border_value); - id.set(0, idx); - id.set(1, idy + 1); - const T bl = tensor_elem_at(in, id, border_mode, constant_border_value); - id.set(0, idx + 1); - id.set(1, idy + 1); - const T br = tensor_elem_at(in, id, border_mode, constant_border_value); - - return tl * (dx_1 * dy_1) + tr * (dx * dy_1) + bl * (dx_1 * dy) + br * (dx * dy); -} - -bool valid_bilinear_policy(float xn, float yn, int width, int height, BorderMode border_mode) -{ - if(border_mode != BorderMode::UNDEFINED) - { - return true; - } - if((0 <= yn + 1) && (yn + 1 < height) && (0 <= xn + 1) && (xn + 1 < width)) - { - return true; - } - return false; -} - -// Sobel 3x3 -template <typename T1, typename T2> -void sobel_3x3(Tensor<T1> &in, Tensor<T2> &out_x, Tensor<T2> &out_y, BorderMode border_mode, uint8_t constant_border_value) -{ - const std::array<int8_t, 9> sobel_x{ { -1, 0, 1, -2, 0, 2, -1, 0, 1 } }; - const std::array<int8_t, 9> sobel_y{ { -1, -2, -1, 0, 0, 0, 1, 2, 1 } }; - - for(int element_idx = 0; element_idx < in.num_elements(); ++element_idx) - { - const Coordinates id = index2coord(in.shape(), element_idx); - - apply_2d_spatial_filter(id, in, out_x, TensorShape(3U, 3U), sobel_x.data(), 1.f, border_mode, constant_border_value); - apply_2d_spatial_filter(id, in, out_y, TensorShape(3U, 3U), sobel_y.data(), 1.f, border_mode, constant_border_value); - } -} - -// Sobel 5x5 -template <typename T1, typename T2> -void sobel_5x5(Tensor<T1> &in, Tensor<T2> &out_x, Tensor<T2> &out_y, BorderMode border_mode, uint8_t constant_border_value) -{ - const std::array<int8_t, 25> sobel_x{ { - -1, -2, 0, 2, 1, - -4, -8, 0, 8, 4, - -6, -12, 0, 12, 6, - -4, -8, 0, 8, 4, - -1, -2, 0, 2, 1 - } }; - - const std::array<int8_t, 25> sobel_y{ { - -1, -4, -6, -4, -1, - -2, -8, -12, -8, -2, - 0, 0, 0, 0, 0, - 2, 8, 12, 8, 2, - 1, 4, 6, 4, 1 - } }; - - for(int element_idx = 0; element_idx < in.num_elements(); ++element_idx) - { - const Coordinates id = index2coord(in.shape(), element_idx); - - apply_2d_spatial_filter(id, in, out_x, TensorShape(5U, 5U), sobel_x.data(), 1.f, border_mode, constant_border_value); - apply_2d_spatial_filter(id, in, out_y, TensorShape(5U, 5U), sobel_y.data(), 1.f, border_mode, constant_border_value); - } -} - -// Sobel 7x7 -template <typename T1, typename T2> -void sobel_7x7(Tensor<T1> &in, Tensor<T2> &out_x, Tensor<T2> &out_y, BorderMode border_mode, uint8_t constant_border_value) -{ - const std::array<int8_t, 49> sobel_x{ { - -1, -4, -5, 0, 5, 4, 1, - -6, -24, -30, 0, 30, 24, 6, - -15, -60, -75, 0, 75, 60, 15, - -20, -80, -100, 0, 100, 80, 20, - -15, -60, -75, 0, 75, 60, 15, - -6, -24, -30, 0, 30, 24, 6, - -1, -4, -5, 0, 5, 4, 1 - } }; - - const std::array<int8_t, 49> sobel_y{ { - -1, -6, -15, -20, -15, -6, -1, - -4, -24, -60, -80, -60, -24, -4, - -5, -30, -75, -100, -75, -30, -5, - 0, 0, 0, 0, 0, 0, 0, - 5, 30, 75, 100, 75, 30, 5, - 4, 24, 60, 80, 60, 24, 4, - 1, 6, 15, 20, 15, 6, 1 - } }; - - for(int element_idx = 0; element_idx < in.num_elements(); ++element_idx) - { - const Coordinates id = index2coord(in.shape(), element_idx); - - apply_2d_spatial_filter(id, in, out_x, TensorShape(7U, 7U), sobel_x.data(), 1.f, border_mode, constant_border_value); - apply_2d_spatial_filter(id, in, out_y, TensorShape(7U, 7U), sobel_y.data(), 1.f, border_mode, constant_border_value); - } -} - -template <typename T> -void non_maxima_suppression_3x3(Tensor<T> &in, Tensor<T> &out, BorderMode border_mode) -{ - for(int i = 0; i < in.num_elements(); ++i) - { - Coordinates coord = index2coord(in.shape(), i); - int x = coord.x(); - int y = coord.y(); - - if(in[i] >= tensor_elem_at(in, Coordinates(x - 1, y - 1), border_mode, 0.f) && in[i] >= tensor_elem_at(in, Coordinates(x, y - 1), border_mode, 0.f) - && in[i] >= tensor_elem_at(in, Coordinates(x + 1, y - 1), border_mode, 0.f) && in[i] >= tensor_elem_at(in, Coordinates(x - 1, y), border_mode, 0.f) - && in[i] > tensor_elem_at(in, Coordinates(x + 1, y), border_mode, 0.f) && in[i] > tensor_elem_at(in, Coordinates(x - 1, y + 1), border_mode, 0.f) - && in[i] > tensor_elem_at(in, Coordinates(x, y + 1), border_mode, 0.f) && in[i] > tensor_elem_at(in, Coordinates(x + 1, y + 1), border_mode, 0.f)) - { - out[i] = in[i]; - } - else - { - out[i] = 0; - } - } -} - -// Harris corners -template <typename T1, typename T2, typename T3> -void harris_corners(Tensor<T1> &in, Tensor<T2> &Gx, Tensor<T2> &Gy, Tensor<T3> &candidates, Tensor<T3> &non_maxima, float threshold, float min_dist, float sensitivity, - int32_t gradient_size, int32_t block_size, KeyPointArray &corners, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(block_size != 3 && block_size != 5 && block_size != 7); - - ValidRegion valid_region = shape_to_valid_region(candidates.shape()); - float norm_factor = 0.f; - - // Sobel - switch(gradient_size) - { - case 3: - sobel_3x3(in, Gx, Gy, border_mode, constant_border_value); - norm_factor = 1.f / (4 * 255 * block_size); - break; - case 5: - sobel_5x5(in, Gx, Gy, border_mode, constant_border_value); - norm_factor = 1.f / (16 * 255 * block_size); - break; - case 7: - sobel_7x7(in, Gx, Gy, border_mode, constant_border_value); - norm_factor = 1.f / (64 * 255 * block_size); - break; - default: - ARM_COMPUTE_ERROR("Gradient size not supported."); - } - - //Calculate scores - for(int i = 0; i < in.num_elements(); ++i) - { - Coordinates in_coord = index2coord(in.shape(), i); - - float Gx2 = 0; - float Gy2 = 0; - float Gxy = 0; - - // Calculate Gx^2, Gy^2 and Gxy within the given window - for(int y = in_coord.y() - block_size / 2; y <= in_coord.y() + block_size / 2; ++y) - { - for(int x = in_coord.x() - block_size / 2; x <= in_coord.x() + block_size / 2; ++x) - { - Coordinates block_coord(x, y); - - float norm_gx = tensor_elem_at(Gx, block_coord, border_mode, static_cast<T2>(constant_border_value)) * norm_factor; - float norm_gy = tensor_elem_at(Gy, block_coord, border_mode, static_cast<T2>(constant_border_value)) * norm_factor; - - Gx2 += std::pow(norm_gx, 2); - Gy2 += std::pow(norm_gy, 2); - Gxy += norm_gx * norm_gy; - } - } - - float trace2 = std::pow(Gx2 + Gy2, 2); - float det = Gx2 * Gy2 - std::pow(Gxy, 2); - float response = det - sensitivity * trace2; - - if(response > threshold) - { - candidates[i] = response; - } - else - { - candidates[i] = 0.f; - } - } - - // Update valid region and remove candidates on borders for border_mode == UNDEFINED - if(border_mode == BorderMode::UNDEFINED) - { - valid_region = shape_to_valid_region(candidates.shape(), true, BorderSize((gradient_size / 2) + (block_size / 2))); - - for(int i = 0; i < candidates.num_elements(); ++i) - { - if(!is_in_valid_region(valid_region, index2coord(candidates.shape(), i))) - { - candidates[i] = 0.f; - } - } - } - - // Suppress non-maxima candidates - non_maxima_suppression_3x3(candidates, non_maxima, border_mode != BorderMode::UNDEFINED ? BorderMode::CONSTANT : BorderMode::UNDEFINED); - if(border_mode == BorderMode::UNDEFINED) - { - valid_region = shape_to_valid_region(non_maxima.shape(), true, BorderSize((gradient_size / 2) + (block_size / 2) + 1)); - } - - // Create vector of candidate corners - KeyPointArray candidates_vector(corners.max_num_values()); - for(int i = 0; i < non_maxima.num_elements(); ++i) - { - Coordinates coord = index2coord(non_maxima.shape(), i); - - if(non_maxima[i] != 0.f && is_in_valid_region(valid_region, coord)) - { - KeyPoint corner; - corner.x = coord.x(); - corner.y = coord.y(); - corner.tracking_status = 1; - corner.strength = non_maxima[i]; - - corner.scale = 0.f; - corner.orientation = 0.f; - corner.error = 0.f; - - candidates_vector.push_back(corner); - } - } - - // If there are any candidates, sort them by strength and add them to the output corners vector if there are no stronger corners within the given euclidean radius - if(candidates_vector.num_values() > 0) - { - std::sort(candidates_vector.buffer(), candidates_vector.buffer() + candidates_vector.num_values(), [](KeyPoint a, KeyPoint b) - { - return a.strength > b.strength; - }); - corners.push_back(candidates_vector.at(0)); - - for(size_t j = 0; j < candidates_vector.num_values(); ++j) - { - bool found = false; - int32_t x = candidates_vector.at(j).x; - int32_t y = candidates_vector.at(j).y; - - for(size_t i = 0; i < corners.num_values(); ++i) - { - int32_t corners_x = corners.at(i).x; - int32_t corners_y = corners.at(i).y; - - // Euclidean distance - if(std::sqrt((std::pow(x - corners_x, 2) + std::pow(y - corners_y, 2))) < min_dist) - { - found = true; - } - } - - // If no stronger corners within the given euclidean radius - if(!found) - { - corners.push_back(candidates_vector.at(j)); - } - } - } -} - -template <typename T> -void compute_min_max(const Tensor<T> &in, void *min, void *max) -{ - using type = typename std::conditional<std::is_same<T, float>::value, float, int32_t>::type; - - // Set min and max to first pixel - type tmp_min = static_cast<type>(in[0]); - type tmp_max = static_cast<type>(in[0]); - - // Look for min and max values - for(int i = 1; i < in.num_elements(); ++i) - { - if(static_cast<type>(in[i]) < tmp_min) - { - tmp_min = static_cast<type>(in[i]); - } - if(static_cast<type>(in[i]) > tmp_max) - { - tmp_max = static_cast<type>(in[i]); - } - } - - *static_cast<type *>(min) = tmp_min; - *static_cast<type *>(max) = tmp_max; -} - -// Min max location -template <typename T1> -void min_max_location(const Tensor<T1> &in, void *min, void *max, IArray<Coordinates2D> &min_loc, IArray<Coordinates2D> &max_loc, uint32_t &min_count, uint32_t &max_count) -{ - const size_t width = in.shape().x(); - - compute_min_max(in, min, max); - - using type = typename std::conditional<std::is_same<T1, float>::value, float, int32_t>::type; - - type min_value = *static_cast<type *>(min); - type max_value = *static_cast<type *>(max); - - min_count = 0; - max_count = 0; - for(int i = 0; i < in.num_elements(); ++i) - { - if(static_cast<type>(in[i]) == min_value) - { - Coordinates2D min_coord; - min_coord.x = static_cast<int32_t>(i % width); - min_coord.y = static_cast<int32_t>(i / width); - - min_loc.push_back(min_coord); - - min_count++; - } - if(static_cast<type>(in[i]) == max_value) - { - Coordinates2D max_coord; - max_coord.x = static_cast<int32_t>(i % width); - max_coord.y = static_cast<int32_t>(i / width); - - max_loc.push_back(max_coord); - - max_count++; - } - } -} - -// Integral Image -void integral_image(const Tensor<uint8_t> &in, Tensor<uint32_t> &out) -{ - // Length of dimensions - const size_t width = in.shape().x(); - const size_t height = in.shape().y(); - const size_t depth = in.shape().z() * in.shape()[3] * in.shape()[4] * in.shape()[5]; - - const size_t image_size = width * height; - - for(size_t z = 0; z < depth; ++z) - { - size_t current_image = z * image_size; - - //First element of each image - out[current_image] = in[current_image]; - - // First row of each image (add only pixel on the left) - for(size_t x = 1; x < width; ++x) - { - out[current_image + x] = static_cast<uint32_t>(in[current_image + x]) + out[current_image + x - 1]; - } - - // Subsequent rows - for(size_t y = 1; y < height; ++y) - { - size_t current_row = current_image + (width * y); - - // First element of each row (add only pixel up) - out[current_row] = static_cast<uint32_t>(in[current_row]) + out[current_row - width]; - - // Following row elements - for(size_t x = 1; x < width; ++x) - { - size_t current_pixel = current_row + x; - - // out = in + up(out) + left(out) - up_left(out) - out[current_pixel] = static_cast<uint32_t>(in[current_pixel]) + out[current_pixel - 1] - + out[current_pixel - width] - out[current_pixel - width - 1]; - } - } - } -} - -// Absolute difference -template <typename T1, typename T2, typename T3> -void absolute_difference(const Tensor<T1> &in1, const Tensor<T2> &in2, Tensor<T3> &out) -{ - using intermediate_type = typename common_promoted_signed_type<T1, T2, T3>::intermediate_type; - - for(int i = 0; i < in1.num_elements(); ++i) - { - intermediate_type val(std::abs(static_cast<intermediate_type>(in1[i]) - static_cast<intermediate_type>(in2[i]))); - out[i] = saturate_cast<T3>(val); - } -} - -// Accumulate -template <typename T1, typename T2> -void accumulate(const Tensor<T1> &in, Tensor<T2> &out) -{ - using intermediate_type = typename common_promoted_signed_type<T1, T2>::intermediate_type; - - for(int i = 0; i < in.num_elements(); ++i) - { - intermediate_type val = static_cast<intermediate_type>(out[i]) + static_cast<intermediate_type>(in[i]); - out[i] = saturate_cast<T2>(val); - } -} - -// Accumulate squared -template <typename T1, typename T2> -void accumulate_squared(const Tensor<T1> &in, Tensor<T2> &out, uint32_t shift) -{ - if(shift > 15) - { - ARM_COMPUTE_ERROR("Shift in accumulate_squared must be within the range [0, 15]"); - } - using intermediate_type = typename common_promoted_signed_type<T1, T2>::intermediate_type; - intermediate_type denom = 1 << shift; - - for(int i = 0; i < in.num_elements(); ++i) - { - intermediate_type val = static_cast<intermediate_type>(out[i]) + (static_cast<intermediate_type>(in[i]) * static_cast<intermediate_type>(in[i]) / denom); - out[i] = saturate_cast<T2>(val); - } -} - -// Accumulate weighted total_size = init_auto_padding(tensor_shape, num_channels, type); -template <typename T> -void accumulate_weighted(const Tensor<T> &in, Tensor<T> &out, float alpha) -{ - if(alpha < 0.f || alpha > 1.f) - { - ARM_COMPUTE_ERROR("Weight (alpha) specified in accumulate_weighted must be within the range [0, 1]"); - } - using intermediate_type = typename common_promoted_signed_type<T>::intermediate_type; - - for(int i = 0; i < in.num_elements(); ++i) - { - double val = (1. - static_cast<double>(alpha)) * static_cast<intermediate_type>(out[i]) + static_cast<double>(alpha) * static_cast<intermediate_type>(in[i]); - out[i] = static_cast<T>(val); - } -} - -// Arithmetic addition -template <typename T1, typename T2, typename T3> -void arithmetic_addition(const Tensor<T1> &in1, const Tensor<T2> &in2, Tensor<T3> &out, ConvertPolicy convert_policy) -{ - using intermediate_type = typename common_promoted_signed_type<T1, T2, T3>::intermediate_type; - - for(int i = 0; i < in1.num_elements(); ++i) - { - intermediate_type val = static_cast<intermediate_type>(in1[i]) + static_cast<intermediate_type>(in2[i]); - out[i] = (convert_policy == ConvertPolicy::SATURATE) ? saturate_cast<T3>(val) : static_cast<T3>(val); - } -} - -// Arithmetic Subtraction -template <typename T1, typename T2, typename T3> -void arithmetic_subtraction(const Tensor<T1> &in1, const Tensor<T2> &in2, Tensor<T3> &out, ConvertPolicy convert_policy) -{ - using intermediate_type = typename common_promoted_signed_type<T1, T2, T3>::intermediate_type; - - for(int i = 0; i < in1.num_elements(); ++i) - { - intermediate_type val = static_cast<intermediate_type>(in1[i]) - static_cast<intermediate_type>(in2[i]); - out[i] = (convert_policy == ConvertPolicy::SATURATE) ? saturate_cast<T3>(val) : static_cast<T3>(val); - } -} - -// Box3x3 filter -template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> -void box3x3(const Tensor<T> &in, Tensor<T> &out, BorderMode border_mode, T constant_border_value) -{ - const std::array<T, 9> filter{ { 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; - float scale = 1.f / static_cast<float>(filter.size()); - for(int element_idx = 0; element_idx < in.num_elements(); ++element_idx) - { - const Coordinates id = index2coord(in.shape(), element_idx); - apply_2d_spatial_filter(id, in, out, TensorShape(3U, 3U), filter.data(), scale, border_mode, constant_border_value); - } -} - -// Depth conversion -template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&is_floating_point<T2>::value, int >::type = 0 > -void depth_convert(const Tensor<T1> &in, Tensor<T2> &out, ConvertPolicy policy, uint32_t shift) -{ - using namespace fixed_point_arithmetic; - - const int fixed_point_position = in.fixed_point_position(); - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = static_cast<float>(fixed_point<T1>(in[i], fixed_point_position, true)); - } -} - -template < typename T1, typename T2, typename std::enable_if < is_floating_point<T1>::value &&std::is_integral<T2>::value, int >::type = 0 > -void depth_convert(const Tensor<T1> &in, Tensor<T2> &out, ConvertPolicy policy, uint32_t shift) -{ - using namespace fixed_point_arithmetic; - - const int fixed_point_position = out.fixed_point_position(); - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = fixed_point<T2>(in[i], fixed_point_position).raw(); - } -} - -template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&std::is_integral<T2>::value &&!std::is_same<T1, T2>::value, int >::type = 0 > -void depth_convert(const Tensor<T1> &in, Tensor<T2> &out, ConvertPolicy policy, uint32_t shift) -{ - // Up-casting - if(std::numeric_limits<T1>::digits <= std::numeric_limits<T2>::digits) - { - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = static_cast<T2>(in[i]) << shift; - } - } - // Down-casting - else - { - for(int i = 0; i < in.num_elements(); ++i) - { - T1 val = in[i] >> shift; - out[i] = ((policy == ConvertPolicy::SATURATE) ? saturate_cast<T2>(val) : static_cast<T2>(val)); - } - } -} - -template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&std::is_integral<T2>::value &&std::is_same<T1, T2>::value, int >::type = 0 > -void depth_convert(const Tensor<T1> &in, Tensor<T2> &out, ConvertPolicy policy, uint32_t shift) -{ - using namespace fixed_point_arithmetic; - bool is_in_place = (&in == &out); - - const int fixed_point_position_in = in.fixed_point_position(); - const int fixed_point_position_out = (is_in_place) ? static_cast<int>(shift) : out.fixed_point_position(); - - if(!is_in_place || (fixed_point_position_in != fixed_point_position_out)) - { - for(int i = 0; i < in.num_elements(); ++i) - { - auto x = fixed_point<T2>(in[i], fixed_point_position_in, true); - x.rescale(fixed_point_position_out); - out[i] = x.raw(); - } - } -} - -template < typename T1, typename T2, typename std::enable_if < is_floating_point<T1>::value &&is_floating_point<T2>::value, int >::type = 0 > -void depth_convert(const Tensor<T1> &in, Tensor<T2> &out, ConvertPolicy policy, uint32_t shift) -{ - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = static_cast<T2>(in[i]); - } -} - -// Gaussian3x3 filter -template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> -void gaussian3x3(const Tensor<T> &in, Tensor<T> &out, BorderMode border_mode, T constant_border_value) -{ - const std::array<T, 9> filter{ { 1, 2, 1, 2, 4, 2, 1, 2, 1 } }; - const float scale = 1.f / 16.f; - for(int element_idx = 0; element_idx < in.num_elements(); ++element_idx) - { - const Coordinates id = index2coord(in.shape(), element_idx); - apply_2d_spatial_filter(id, in, out, TensorShape(3U, 3U), filter.data(), scale, border_mode, constant_border_value); - } -} - -// Gaussian5x5 filter -template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> -void gaussian5x5(const Tensor<T> &in, Tensor<T> &out, BorderMode border_mode, T constant_border_value) -{ - const std::array<T, 25> filter{ { - 1, 4, 6, 4, 1, - 4, 16, 24, 16, 4, - 6, 24, 36, 24, 6, - 4, 16, 24, 16, 4, - 1, 4, 6, 4, 1 - } }; - const float scale = 1.f / 256.f; - for(int element_idx = 0; element_idx < in.num_elements(); ++element_idx) - { - const Coordinates id = index2coord(in.shape(), element_idx); - apply_2d_spatial_filter(id, in, out, TensorShape(5U, 5U), filter.data(), scale, border_mode, constant_border_value); - } -} - -// Non linear filter -template <typename T> -void non_linear_filter(const Tensor<T> &in, Tensor<T> &out, NonLinearFilterFunction function, unsigned int mask_size, - MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode, uint8_t constant_border_value) -{ - ARM_COMPUTE_ERROR_ON(pattern == MatrixPattern::OTHER && mask == nullptr); - - using intermediate_type = typename common_promoted_signed_type<T>::intermediate_type; - - const int sq_mask_size = mask_size * mask_size; - const int half_mask_size = mask_size / 2; - std::vector<intermediate_type> vals(sq_mask_size); - intermediate_type current_value = 0; - - const ValidRegion valid_region = shape_to_valid_region(in.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(half_mask_size)); - - for(int element_idx = 0, count = 0, index = 0; element_idx < in.num_elements(); ++element_idx, count = 0, index = 0) - { - Coordinates id = index2coord(in.shape(), element_idx); - if(is_in_valid_region(valid_region, id)) - { - int idx = id.x(); - int idy = id.y(); - for(int y = idy - half_mask_size; y <= idy + half_mask_size; ++y) - { - for(int x = idx - half_mask_size; x <= idx + half_mask_size; ++x, ++index) - { - id.set(0, x); - id.set(1, y); - current_value = tensor_elem_at(in, id, border_mode, constant_border_value); - - if(mask[index] == 255) - { - vals[count] = static_cast<intermediate_type>(current_value); - ++count; - } - } - } - std::sort(vals.begin(), vals.begin() + count); - switch(function) - { - case NonLinearFilterFunction::MIN: - out[element_idx] = saturate_cast<T>(vals[0]); - break; - case NonLinearFilterFunction::MAX: - out[element_idx] = saturate_cast<T>(vals[count - 1]); - break; - case NonLinearFilterFunction::MEDIAN: - out[element_idx] = saturate_cast<T>(vals[count / 2]); - break; - default: - ARM_COMPUTE_ERROR("Unsupported NonLinearFilter function."); - } - } - } -} - -// Pixel-wise multiplication -template <typename T1, typename T2, typename T3> -void pixel_wise_multiplication(const Tensor<T1> &in1, const Tensor<T2> &in2, Tensor<T3> &out, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy) -{ - if(scale < 0) - { - ARM_COMPUTE_ERROR("Scale of pixel-wise multiplication must be non-negative"); - } - using intermediate_type = typename common_promoted_signed_type<T1, T2, T3>::intermediate_type; - for(int i = 0; i < in1.num_elements(); ++i) - { - double val = static_cast<intermediate_type>(in1[i]) * static_cast<intermediate_type>(in2[i]) * static_cast<double>(scale); - if(is_floating_point<T3>::value) - { - out[i] = val; - } - else - { - double rounded_val = 0; - switch(rounding_policy) - { - case(RoundingPolicy::TO_ZERO): - rounded_val = support::cpp11::trunc(val); - break; - case(RoundingPolicy::TO_NEAREST_UP): - rounded_val = round_half_up(val); - break; - case(RoundingPolicy::TO_NEAREST_EVEN): - rounded_val = round_half_even(val); - break; - default: - ARM_COMPUTE_ERROR("Unsupported rounding policy"); - } - out[i] = (convert_policy == ConvertPolicy::SATURATE) ? saturate_cast<T3>(rounded_val) : static_cast<T3>(rounded_val); - } - } -} - -// Fixed-point Pixel-wise Multiplication -template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> -void fixed_point_pixel_wise_multiplication(const Tensor<T> &in1, const Tensor<T> &in2, Tensor<T> &out, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy) -{ - using namespace fixed_point_arithmetic; - - const int fixed_point_position = in1.fixed_point_position(); - - ARM_COMPUTE_ERROR_ON_MSG(in1.data_type() != in2.data_type() || in1.data_type() != out.data_type(), - "Tensors must all have the same DataType"); - ARM_COMPUTE_ERROR_ON_MSG(fixed_point_position != in2.fixed_point_position() || fixed_point_position != out.fixed_point_position(), - "Fixed-point position must be the same for both inputs and outputs"); - - // Validate fixed_point_position - ARM_COMPUTE_ERROR_ON((in1.data_type() == DataType::QS8) && (fixed_point_position == 0 || fixed_point_position > 7)); - ARM_COMPUTE_ERROR_ON((in1.data_type() == DataType::QS16) && (fixed_point_position == 0 || fixed_point_position > 15)); - - const fixed_point<T> fp_scale(scale, fixed_point_position); - const bool is_sat = convert_policy == ConvertPolicy::SATURATE; - - for(int i = 0; i < in1.num_elements(); ++i) - { - const fixed_point<T> val1(in1[i], fixed_point_position, true); - fixed_point<T> res(in2[i], fixed_point_position, true); - if(is_sat) - { - res = mul(mul(res, val1), fp_scale); - } - else - { - res = mul<OverflowPolicy::WRAP>(mul<OverflowPolicy::WRAP>(res, val1), fp_scale); - } - out[i] = res.raw(); - } -} - -//Table Lookup -template <typename T, typename T1> -void table_lookup(const Tensor<T> &in, Tensor<T> &out, std::map<T1, T1> &lut) -{ - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = static_cast<T>(lut[in[i]]); - } -} - -// Threshold -template <typename T> -void threshold(const Tensor<T> &in, Tensor<T> &out, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper) -{ - switch(type) - { - case ThresholdType::BINARY: - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = ((in[i] > threshold) ? true_value : false_value); - } - break; - case ThresholdType::RANGE: - for(int i = 0; i < in.num_elements(); ++i) - { - if(in[i] > upper) - { - out[i] = false_value; - } - else if(in[i] < threshold) - { - out[i] = false_value; - } - else - { - out[i] = true_value; - } - } - break; - default: - ARM_COMPUTE_ERROR("Thresholding type not recognised"); - break; - } -} - -// Warp Perspective -template <typename T> -void warp_perspective(const Tensor<T> &in, Tensor<T> &out, Tensor<T> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value) -{ - // x0 = M00 * x + M01 * y + M02 - // y0 = M10 * x + M11 * y + M12 - // z0 = M20 * x + M21 * y + M22 - // xn = x0 / z0 - // yn = y0 / z0 - const float M00 = matrix[0]; - const float M10 = matrix[1]; - const float M20 = matrix[2]; - const float M01 = matrix[0 + 1 * 3]; - const float M11 = matrix[1 + 1 * 3]; - const float M21 = matrix[2 + 1 * 3]; - const float M02 = matrix[0 + 2 * 3]; - const float M12 = matrix[1 + 2 * 3]; - const float M22 = matrix[2 + 2 * 3]; - - const int width = in.shape().x(); - const int height = in.shape().y(); - - for(int element_idx = 0; element_idx < in.num_elements(); ++element_idx) - { - valid_mask[element_idx] = 1; - Coordinates id = index2coord(in.shape(), element_idx); - int idx = id.x(); - int idy = id.y(); - const float z0 = M20 * idx + M21 * idy + M22; - - float x0 = (M00 * idx + M01 * idy + M02); - float y0 = (M10 * idx + M11 * idy + M12); - - float xn = x0 / z0; - float yn = y0 / z0; - id.set(0, static_cast<int>(std::floor(xn))); - id.set(1, static_cast<int>(std::floor(yn))); - if((0 <= yn) && (yn < height) && (0 <= xn) && (xn < width)) - { - switch(policy) - { - case InterpolationPolicy::NEAREST_NEIGHBOR: - out[element_idx] = tensor_elem_at(in, id, border_mode, constant_border_value); - break; - case InterpolationPolicy::BILINEAR: - (valid_bilinear_policy(xn, yn, width, height, border_mode)) ? out[element_idx] = bilinear_policy(in, id, xn, yn, border_mode, constant_border_value) : valid_mask[element_idx] = 0; - break; - case InterpolationPolicy::AREA: - default: - ARM_COMPUTE_ERROR("Interpolation not supported"); - } - } - else - { - if(border_mode == BorderMode::UNDEFINED) - { - valid_mask[element_idx] = 0; - } - else - { - switch(policy) - { - case InterpolationPolicy::NEAREST_NEIGHBOR: - if(border_mode == BorderMode::CONSTANT) - { - out[element_idx] = constant_border_value; - } - else if(border_mode == BorderMode::REPLICATE) - { - id.set(0, std::max(0, std::min(static_cast<int>(xn), width - 1))); - id.set(1, std::max(0, std::min(static_cast<int>(yn), height - 1))); - out[element_idx] = in[coord2index(in.shape(), id)]; - } - break; - case InterpolationPolicy::BILINEAR: - out[element_idx] = bilinear_policy(in, id, xn, yn, border_mode, constant_border_value); - break; - case InterpolationPolicy::AREA: - default: - ARM_COMPUTE_ERROR("Interpolation not supported"); - } - } - } - } -} - -// Batch Normalization Layer for fixed point type -template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type * = nullptr> -void batch_normalization_layer(const Tensor<T> &in, Tensor<T> &out, const Tensor<T> &mean, const Tensor<T> &var, const Tensor<T> &beta, const Tensor<T> &gamma, float epsilon, int fixed_point_position) -{ - const int cols = static_cast<int>(in.shape()[0]); - const int rows = static_cast<int>(in.shape()[1]); - const int depth = static_cast<int>(in.shape()[2]); - int upper_dims = in.shape().total_size() / (cols * rows * depth); - - for(int r = 0; r < upper_dims; ++r) - { - for(int i = 0; i < depth; ++i) - { - for(int k = 0; k < rows; ++k) - { - for(int l = 0; l < cols; ++l) - { - const int pos = l + k * cols + i * rows * cols + r * cols * rows * depth; - fixed_point_arithmetic::fixed_point<T> in_qs(in[pos], fixed_point_position, true); - fixed_point_arithmetic::fixed_point<T> var_qs(var[i], fixed_point_position, true); - fixed_point_arithmetic::fixed_point<T> mean_qs(mean[i], fixed_point_position, true); - fixed_point_arithmetic::fixed_point<T> beta_qs(beta[i], fixed_point_position, true); - fixed_point_arithmetic::fixed_point<T> gamma_qs(gamma[i], fixed_point_position, true); - fixed_point_arithmetic::fixed_point<T> epsilon_qs(epsilon, fixed_point_position); - - auto denominator = fixed_point_arithmetic::inv_sqrt(var_qs + epsilon_qs); - auto numerator = in_qs - mean_qs; - auto x_bar = numerator * denominator; - x_bar = beta_qs + x_bar * gamma_qs; - out[pos] = x_bar.raw(); - } - } - } - } -} - -// Batch Normalization Layer for floating point type -template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type * = nullptr> -void batch_normalization_layer(const Tensor<T> &in, Tensor<T> &out, const Tensor<T> &mean, const Tensor<T> &var, const Tensor<T> &beta, const Tensor<T> &gamma, float epsilon, int fixed_point_position) -{ - const int cols = static_cast<int>(in.shape()[0]); - const int rows = static_cast<int>(in.shape()[1]); - const int depth = static_cast<int>(in.shape()[2]); - int upper_dims = in.shape().total_size() / (cols * rows * depth); - - for(int r = 0; r < upper_dims; ++r) - { - for(int i = 0; i < depth; ++i) - { - for(int k = 0; k < rows; ++k) - { - for(int l = 0; l < cols; ++l) - { - const int pos = l + k * cols + i * rows * cols + r * cols * rows * depth; - const float denominator = sqrt(var[i] + epsilon); - const float numerator = in[pos] - mean[i]; - const float x_bar = numerator / denominator; - out[pos] = beta[i] + x_bar * gamma[i]; - } - } - } - } -} - -// ROI Pooling layer -template <typename T> -void roi_pooling_layer(const Tensor<T> &in, Tensor<T> &out, const std::vector<ROI> &rois, const ROIPoolingLayerInfo &pool_info) -{ - const int num_rois = rois.size(); - const int width_in = in.shape().x(); - const int height_in = in.shape().y(); - const int fms = in.shape().z(); - const int volume_in = width_in * height_in * fms; - const int pool_w = pool_info.pooled_width(); - const int pool_h = pool_info.pooled_height(); - const int volume_out = pool_w * pool_h * fms; - const float roi_scale = pool_info.spatial_scale(); - - // Iterate through all rois - for(int roi_idx = 0; roi_idx < num_rois; ++roi_idx) - { - // Get dimensions of current ROI - const ROI &roi = rois[roi_idx]; - - int batch_id = roi.batch_idx; - int roi_start_x = support::cpp11::round(roi.rect.x * roi_scale); - int roi_start_y = support::cpp11::round(roi.rect.y * roi_scale); - int roi_width = std::max(support::cpp11::round(roi.rect.width * roi_scale), 1.f); - int roi_height = std::max(support::cpp11::round(roi.rect.height * roi_scale), 1.f); - - // Determine pooling regions - float pool_region_size_x = static_cast<float>(roi_width) / pool_w; - float pool_region_size_y = static_cast<float>(roi_height) / pool_h; - - // Iterate through all channel - for(int fm = 0; fm < fms; ++fm) - { - // Calculate each output pixel - for(int py = 0; py < pool_h; ++py) - { - for(int px = 0; px < pool_w; ++px) - { - int region_start_x = static_cast<int>(std::floor(px * pool_region_size_x)); - int region_end_x = static_cast<int>(std::ceil((px + 1) * pool_region_size_x)); - int region_start_y = static_cast<int>(std::floor(py * pool_region_size_y)); - int region_end_y = static_cast<int>(std::ceil((py + 1) * pool_region_size_y)); - - region_start_x = std::min(std::max(region_start_x + roi_start_x, 0), width_in); - region_end_x = std::min(std::max(region_end_x + roi_start_x, 0), width_in); - region_start_y = std::min(std::max(region_start_y + roi_start_y, 0), height_in); - region_end_y = std::min(std::max(region_end_y + roi_start_y, 0), height_in); - - // Iterate through each pixel in the pooling region - if((region_end_x <= region_start_x) || (region_end_y <= region_start_y)) - { - out[roi_idx * volume_out + fm * pool_w * pool_h + py * pool_w + px] = 0; - } - else - { - T curr_max = std::numeric_limits<T>::lowest(); - for(int j = region_start_y; j < region_end_y; ++j) - { - for(int i = region_start_x; i < region_end_x; ++i) - { - const auto val = in[batch_id * volume_in + fm * width_in * height_in + j * width_in + i]; - curr_max = std::max(val, curr_max); - } - } - out[roi_idx * volume_out + fm * pool_w * pool_h + py * pool_w + px] = curr_max; - } - } - } - } - } -} - -// Fixed point operations -template <typename T> -void fixed_point_operation(const Tensor<T> &in, Tensor<T> &out, FixedPointOp op) -{ - int p = in.fixed_point_position(); - switch(op) - { - case FixedPointOp::EXP: - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = fixed_point_arithmetic::exp(fixed_point_arithmetic::fixed_point<T>(in[i], p, true)).raw(); - } - break; - case FixedPointOp::LOG: - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = fixed_point_arithmetic::log(fixed_point_arithmetic::fixed_point<T>(in[i], p, true)).raw(); - } - break; - case FixedPointOp::INV_SQRT: - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = fixed_point_arithmetic::inv_sqrt(fixed_point_arithmetic::fixed_point<T>(in[i], p, true)).raw(); - } - break; - case FixedPointOp::RECIPROCAL: - for(int i = 0; i < in.num_elements(); ++i) - { - out[i] = fixed_point_arithmetic::div(fixed_point_arithmetic::fixed_point<T>(1, p), fixed_point_arithmetic::fixed_point<T>(in[i], p, true)).raw(); - } - break; - default: - ARM_COMPUTE_ERROR("Fixed point operation not supported"); - break; - } -} - -// Tensor print -template <typename T> -void print(const Tensor<T> &in, std::ostream &out) -{ - out << "\n"; - for(int i = 0; i < in.num_elements(); ++i) - { - out << in[i] << " "; - } - out << "\n"; -} -} // namespace tensor_operations -} // namespace validation -} // namespace test -} // namespace arm_compute - -#endif /* __ARM_COMPUTE_TEST_TENSOR_OPERATIONS_H__ */ diff --git a/tests/validation/TensorVisitors.h b/tests/validation/TensorVisitors.h deleted file mode 100644 index a15d2ad1dd..0000000000 --- a/tests/validation/TensorVisitors.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * 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. - */ -#ifndef __ARM_COMPUTE_TEST_TENSOR_VISITORS_H__ -#define __ARM_COMPUTE_TEST_TENSOR_VISITORS_H__ - -#include "Tensor.h" -#include "TensorOperations.h" -#include "arm_compute/core/Error.h" -#include "arm_compute/core/Helpers.h" -#include "arm_compute/runtime/Lut.h" - -#include "boost_wrapper.h" - -#include <algorithm> -#include <map> -#include <memory> -#include <ostream> -#include <vector> - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -namespace tensor_visitors -{ -// Min max location visitor -struct min_max_location_visitor : public boost::static_visitor<> -{ -public: - explicit min_max_location_visitor(void *min, void *max, IArray<Coordinates2D> &min_loc, IArray<Coordinates2D> &max_loc, uint32_t &min_count, uint32_t &max_count) - : _min(min), _max(max), _min_loc(min_loc), _max_loc(max_loc), _min_count(min_count), _max_count(max_count) - { - } - template <typename T1> - void operator()(const Tensor<T1> &in) const - { - tensor_operations::min_max_location(in, _min, _max, _min_loc, _max_loc, _min_count, _max_count); - } - -private: - void *_min; - void *_max; - IArray<Coordinates2D> &_min_loc; - IArray<Coordinates2D> &_max_loc; - uint32_t &_min_count; - uint32_t &_max_count; -}; -// Absolute Difference visitor -struct absolute_difference_visitor : public boost::static_visitor<> -{ -public: - template <typename T1, typename T2, typename T3> - void operator()(const Tensor<T1> &in1, const Tensor<T2> &in2, Tensor<T3> &out) const - { - tensor_operations::absolute_difference(in1, in2, out); - } -}; -// Arithmetic Addition visitor -struct arithmetic_addition_visitor : public boost::static_visitor<> -{ -public: - explicit arithmetic_addition_visitor(ConvertPolicy convert_policy) - : _policy(convert_policy) - { - } - - template <typename T1, typename T2, typename T3> - void operator()(const Tensor<T1> &in1, const Tensor<T2> &in2, Tensor<T3> &out) const - { - tensor_operations::arithmetic_addition(in1, in2, out, _policy); - } - -private: - ConvertPolicy _policy; -}; -// Arithmetic Subtraction visitor -struct arithmetic_subtraction_visitor : public boost::static_visitor<> -{ -public: - explicit arithmetic_subtraction_visitor(ConvertPolicy convert_policy) - : _policy(convert_policy) - { - } - - template <typename T1, typename T2, typename T3> - void operator()(const Tensor<T1> &in1, const Tensor<T2> &in2, Tensor<T3> &out) const - { - tensor_operations::arithmetic_subtraction(in1, in2, out, _policy); - } - -private: - ConvertPolicy _policy; -}; -// Depth Convert visitor -struct depth_convert_visitor : public boost::static_visitor<> -{ -public: - explicit depth_convert_visitor(ConvertPolicy policy, uint32_t shift) - : _policy(policy), _shift(shift) - { - } - - template <typename T1, typename T2> - void operator()(const Tensor<T1> &in, Tensor<T2> &out) const - { - tensor_operations::depth_convert(in, out, _policy, _shift); - } - -private: - ConvertPolicy _policy; - uint32_t _shift; -}; -// Pixel-wise Multiplication visitor -struct pixel_wise_multiplication_visitor : public boost::static_visitor<> -{ -public: - explicit pixel_wise_multiplication_visitor(float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy) - : _scale(scale), _convert_policy(convert_policy), _rounding_policy(rounding_policy) - { - } - - template <typename T1, typename T2, typename T3> - void operator()(const Tensor<T1> &in1, const Tensor<T2> &in2, Tensor<T3> &out) const - { - tensor_operations::pixel_wise_multiplication(in1, in2, out, _scale, _convert_policy, _rounding_policy); - } - -private: - float _scale; - ConvertPolicy _convert_policy; - RoundingPolicy _rounding_policy; -}; -// Fixed Point Pixel-wise Multiplication visitor -struct fixed_point_pixel_wise_multiplication_visitor : public boost::static_visitor<> -{ -public: - explicit fixed_point_pixel_wise_multiplication_visitor(const TensorVariant &in1, const TensorVariant &in2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy) - : _in1(in1), _in2(in2), _scale(scale), _convert_policy(convert_policy), _rounding_policy(rounding_policy) - { - } - - template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> - void operator()(Tensor<T> &out) const - { - const Tensor<T> &in1 = boost::get<Tensor<T>>(_in1); - const Tensor<T> &in2 = boost::get<Tensor<T>>(_in2); - tensor_operations::fixed_point_pixel_wise_multiplication(in1, in2, out, _scale, _convert_policy, _rounding_policy); - } - template < typename T, typename std::enable_if < !std::is_integral<T>::value, int >::type = 0 > - void operator()(Tensor<T> &out) const - { - ARM_COMPUTE_ERROR("NOT SUPPORTED!"); - } - -private: - const TensorVariant &_in1; - const TensorVariant &_in2; - float _scale; - ConvertPolicy _convert_policy; - RoundingPolicy _rounding_policy; -}; -// Table lookup operation -template <typename T1> -struct table_lookup : public boost::static_visitor<> -{ -public: - explicit table_lookup(const TensorVariant &in, std::map<T1, T1> &lut) - : _in(in), _lut(lut) - { - } - - template <typename T> - void operator()(Tensor<T> &out) const - { - const auto &in = boost::get<Tensor<T>>(_in); - tensor_operations::table_lookup(in, out, _lut); - } - -private: - const TensorVariant &_in; - std::map<T1, T1> &_lut; -}; -template struct arm_compute::test::validation::tensor_visitors::table_lookup<uint8_t>; -template struct arm_compute::test::validation::tensor_visitors::table_lookup<int16_t>; - -// Batch Normalization Layer visitor -struct batch_normalization_layer_visitor : public boost::static_visitor<> -{ -public: - explicit batch_normalization_layer_visitor(const TensorVariant &in, const TensorVariant &mean, const TensorVariant &var, const TensorVariant &beta, const TensorVariant &gamma, float epsilon, - int fixed_point_position = 0) - : _in(in), _mean(mean), _var(var), _beta(beta), _gamma(gamma), _epsilon(epsilon), _fixed_point_position(fixed_point_position) - { - } - - template <typename T> - void operator()(Tensor<T> &out) const - { - const Tensor<T> &in = boost::get<Tensor<T>>(_in); - const Tensor<T> &mean = boost::get<Tensor<T>>(_mean); - const Tensor<T> &var = boost::get<Tensor<T>>(_var); - const Tensor<T> &beta = boost::get<Tensor<T>>(_beta); - const Tensor<T> &gamma = boost::get<Tensor<T>>(_gamma); - tensor_operations::batch_normalization_layer(in, out, mean, var, beta, gamma, _epsilon, _fixed_point_position); - } - -private: - const TensorVariant &_in, &_mean, &_var, &_beta, &_gamma; - float _epsilon; - int _fixed_point_position; -}; - -// ROI Pooling layer -struct roi_pooling_layer_visitor : public boost::static_visitor<> -{ -public: - explicit roi_pooling_layer_visitor(const TensorVariant &in, const std::vector<ROI> &rois, ROIPoolingLayerInfo pool_info) - : _in(in), _rois(rois), _pool_info(pool_info) - { - } - - template <typename T> - void operator()(Tensor<T> &out) const - { - const Tensor<T> &in = boost::get<Tensor<T>>(_in); - tensor_operations::roi_pooling_layer(in, out, _rois, _pool_info); - } - -private: - const TensorVariant &_in; - const std::vector<ROI> &_rois; - ROIPoolingLayerInfo _pool_info; -}; - -// Fixed Point operations visitor -struct fixed_point_operation_visitor : public boost::static_visitor<> -{ -public: - explicit fixed_point_operation_visitor(const TensorVariant &in, FixedPointOp op) - : _in(in), _op(op) - { - } - - template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> - void operator()(Tensor<T> &out) const - { - const Tensor<T> &in = boost::get<Tensor<T>>(_in); - tensor_operations::fixed_point_operation(in, out, _op); - } - template < typename T, typename std::enable_if < !std::is_integral<T>::value, int >::type = 0 > - void operator()(Tensor<T> &out) const - { - ARM_COMPUTE_ERROR("NOT SUPPORTED!"); - } - -private: - const TensorVariant &_in; - FixedPointOp _op; -}; -// Print Tensor visitor -struct print_visitor : public boost::static_visitor<> -{ -public: - explicit print_visitor(std::ostream &out) - : _out(out) - { - } - - template <typename T> - void operator()(const Tensor<T> &in) const - { - tensor_operations::print(in, _out); - } - -private: - std::ostream &_out; -}; -} // namespace tensor_visitors -} // namespace validation -} // namespace test -} // namespace arm_compute - -#endif /* __ARM_COMPUTE_TEST_TENSOR_VISITORS_H__ */ diff --git a/tests/validation/UNIT/CMakeLists.txt b/tests/validation/UNIT/CMakeLists.txt deleted file mode 100644 index a0603f150c..0000000000 --- a/tests/validation/UNIT/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# 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. -cmake_minimum_required (VERSION 3.1) - -set(arm_compute_test_validation_UNIT_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/TensorInfo.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Utils.cpp -) - -add_library(arm_compute_test_validation_UNIT OBJECT - ${arm_compute_test_validation_UNIT_SOURCE_FILES} -) - -set(arm_compute_test_validation_TARGET_OBJECTS - ${arm_compute_test_validation_TARGET_OBJECTS} - $<TARGET_OBJECTS:arm_compute_test_validation_UNIT> - PARENT_SCOPE -) diff --git a/tests/validation/UNIT/FixedPoint.cpp b/tests/validation/UNIT/FixedPoint.cpp deleted file mode 100644 index 00cab9eb29..0000000000 --- a/tests/validation/UNIT/FixedPoint.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 "validation/FixedPoint.h" - -#include "TypePrinter.h" -#include "Utils.h" -#include "support/ToolchainSupport.h" -#include "validation/Validation.h" -#include "validation/ValidationUserConfiguration.h" - -#include "boost_wrapper.h" - -#include <fstream> -#include <vector> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -std::string func_names[] = -{ - "add", "sub", "mul", "exp", "log", "inv_sqrt" -}; -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(UNIT) -BOOST_AUTO_TEST_SUITE(FixedPoint) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(FixedPointQS8Inputs, boost::unit_test::data::make(func_names) * boost::unit_test::data::xrange(1, 7), func_name, frac_bits) -{ - const std::string base_file_name = user_config.path.get() + "/dumps/" + func_name + "_Q8." + support::cpp11::to_string(frac_bits); - std::ifstream inputs_file{ base_file_name + ".in", std::ios::binary | std::ios::in }; - - BOOST_TEST_INFO(base_file_name + ".in"); - BOOST_TEST_REQUIRE(inputs_file.good()); - - float float_val = 0.f; - - // Read first value - inputs_file.read(reinterpret_cast<char *>(&float_val), sizeof(float_val)); - - while(inputs_file.good()) - { - // Convert to fixed point - fixed_point_arithmetic::fixed_point<int8_t> in_val(float_val, frac_bits); - - // Check that the value didn't change - BOOST_TEST(static_cast<float>(in_val) == float_val); - - // Read next value - inputs_file.read(reinterpret_cast<char *>(&float_val), sizeof(float_val)); - } -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -//FIXME: Figure out how to handle expected failures properly -// The last input argument specifies the expected number of failures for a -// given combination of (function name, number of fractional bits) as defined -// by the first two arguments. -BOOST_DATA_TEST_CASE(FixedPointQS8Outputs, (boost::unit_test::data::make(func_names) * boost::unit_test::data::xrange(1, 7)) ^ (boost::unit_test::data::make({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 13, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 33, 96 })), - func_name, frac_bits, expected_failures) -{ - const std::string base_file_name = user_config.path.get() + "/dumps/" + func_name + "_Q8." + support::cpp11::to_string(frac_bits); - std::ifstream inputs_file{ base_file_name + ".in", std::ios::binary | std::ios::in }; - std::ifstream reference_file{ base_file_name + ".out", std::ios::binary | std::ios::in }; - - BOOST_TEST_INFO(base_file_name + ".in"); - BOOST_TEST_REQUIRE(inputs_file.good()); - BOOST_TEST_INFO(base_file_name + ".out"); - BOOST_TEST_REQUIRE(reference_file.good()); - - const float step_size = std::pow(2.f, -frac_bits); - - float float_val = 0.f; - float ref_val = 0.f; - int64_t num_mismatches = 0; - - // Read first values - inputs_file.read(reinterpret_cast<char *>(&float_val), sizeof(float_val)); - reference_file.read(reinterpret_cast<char *>(&ref_val), sizeof(ref_val)); - - while(inputs_file.good() && reference_file.good()) - { - fixed_point_arithmetic::fixed_point<int8_t> in_val(float_val, frac_bits); - fixed_point_arithmetic::fixed_point<int8_t> out_val(0.f, frac_bits); - - float tolerance = 0.f; - - if(func_name == "add") - { - out_val = in_val + in_val; - } - else if(func_name == "sub") - { - out_val = in_val - in_val; //NOLINT - } - else if(func_name == "mul") - { - tolerance = 1.f * step_size; - out_val = in_val * in_val; - } - else if(func_name == "exp") - { - tolerance = 2.f * step_size; - out_val = fixed_point_arithmetic::exp(in_val); - } - else if(func_name == "log") - { - tolerance = 4.f * step_size; - out_val = fixed_point_arithmetic::log(in_val); - } - else if(func_name == "inv_sqrt") - { - tolerance = 5.f * step_size; - out_val = fixed_point_arithmetic::inv_sqrt(in_val); - } - - if(std::abs(static_cast<float>(out_val) - ref_val) > tolerance) - { - BOOST_TEST_INFO("input = " << in_val); - BOOST_TEST_INFO("output = " << out_val); - BOOST_TEST_INFO("reference = " << ref_val); - BOOST_TEST_INFO("tolerance = " << tolerance); - BOOST_TEST_WARN((std::abs(static_cast<float>(out_val) - ref_val) <= tolerance)); - - ++num_mismatches; - } - - // Read next values - inputs_file.read(reinterpret_cast<char *>(&float_val), sizeof(float_val)); - reference_file.read(reinterpret_cast<char *>(&ref_val), sizeof(ref_val)); - } - - BOOST_TEST(num_mismatches == expected_failures); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/UNIT/TensorInfo.cpp b/tests/validation/UNIT/TensorInfo.cpp deleted file mode 100644 index c74cfebfe4..0000000000 --- a/tests/validation/UNIT/TensorInfo.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 "TypePrinter.h" -#include "validation/Validation.h" - -#include "arm_compute/core/TensorInfo.h" -#include "arm_compute/core/Types.h" - -#include "boost_wrapper.h" - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(UNIT) -BOOST_AUTO_TEST_SUITE(TensorInfoValidation) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(AutoPadding, - boost::unit_test::data::make({ TensorShape{}, - TensorShape{ 10U }, - TensorShape{ 10U, 10U }, - TensorShape{ 10U, 10U, 10U }, - TensorShape{ 10U, 10U, 10U, 10U }, - TensorShape{ 10U, 10U, 10U, 10U, 10U }, - TensorShape{ 10U, 10U, 10U, 10U, 10U, 10U } - }) - ^ boost::unit_test::data::make({ PaddingSize{ 0, 0, 0, 0 }, - PaddingSize{ 0, 36, 0, 4 }, - PaddingSize{ 4, 36, 4, 4 }, - PaddingSize{ 4, 36, 4, 4 }, - PaddingSize{ 4, 36, 4, 4 }, - PaddingSize{ 4, 36, 4, 4 }, - PaddingSize{ 4, 36, 4, 4 } - }) - ^ boost::unit_test::data::make({ Strides{}, - Strides{ 1U }, - Strides{ 1U, 50U }, - Strides{ 1U, 50U, 900U }, - Strides{ 1U, 50U, 900U, 9000U }, - Strides{ 1U, 50U, 900U, 9000U, 90000U }, - Strides{ 1U, 50U, 900U, 9000U, 90000U, 900000U } - }) - ^ boost::unit_test::data::make( -{ - 0, - 4, - 204, - 204, - 204, - 204, - 204, -}), -shape, auto_padding, strides, offset) -{ - TensorInfo info{ shape, Format::U8 }; - - BOOST_TEST(!info.has_padding()); - - info.auto_padding(); - - validate(info.padding(), auto_padding); - BOOST_TEST(compare_dimensions(info.strides_in_bytes(), strides)); - BOOST_TEST(info.offset_first_element_in_bytes() == offset); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/UNIT/TensorShape.cpp b/tests/validation/UNIT/TensorShape.cpp deleted file mode 100644 index 4c1ef680b5..0000000000 --- a/tests/validation/UNIT/TensorShape.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 "TypePrinter.h" -#include "validation/Validation.h" - -#include "arm_compute/core/TensorShape.h" - -#include "boost_wrapper.h" - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(UNIT) -BOOST_AUTO_TEST_SUITE(TensorShapeValidation) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Construction, - boost::unit_test::data::make({ TensorShape{}, - TensorShape{ 1U }, - TensorShape{ 2U }, - TensorShape{ 2U, 3U }, - TensorShape{ 2U, 3U, 5U }, - TensorShape{ 2U, 3U, 5U, 7U }, - TensorShape{ 2U, 3U, 5U, 7U, 11U }, - TensorShape{ 2U, 3U, 5U, 7U, 11U, 13U } - }) - ^ boost::unit_test::data::make({ 0, 0, 1, 2, 3, 4, 5, 6 }) ^ boost::unit_test::data::make({ 0, 1, 2, 6, 30, 210, 2310, 30030 }), - shape, num_dimensions, total_size) -{ - BOOST_TEST(shape.num_dimensions() == num_dimensions); - BOOST_TEST(shape.total_size() == total_size); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(SetEmpty, boost::unit_test::data::make({ 0, 1, 2, 3, 4, 5 }), dimension) -{ - TensorShape shape; - - shape.set(dimension, 10); - - BOOST_TEST(shape.num_dimensions() == dimension + 1); - BOOST_TEST(shape.total_size() == 10); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/UNIT/Utils.cpp b/tests/validation/UNIT/Utils.cpp deleted file mode 100644 index e28ca19620..0000000000 --- a/tests/validation/UNIT/Utils.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 "Utils.h" - -#include "TypePrinter.h" -#include "validation/Validation.h" - -#include "boost_wrapper.h" - -#include <stdexcept> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(UNIT) -BOOST_AUTO_TEST_SUITE(Utils) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RoundHalfUp, boost::unit_test::data::make({ 1.f, 1.2f, 1.5f, 2.5f, 2.9f, -3.f, -3.5f, -3.8f, -4.3f, -4.5f }) ^ boost::unit_test::data::make({ 1.f, 1.f, 2.f, 3.f, 3.f, -3.f, -3.f, -4.f, -4.f, -4.f }), - value, result) -{ - BOOST_TEST(round_half_up(value) == result); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(RoundHalfEven, boost::unit_test::data::make({ 1.f, 1.2f, 1.5f, 2.5f, 2.9f, -3.f, -3.5f, -3.8f, -4.3f, -4.5f }) ^ boost::unit_test::data::make({ 1.f, 1.f, 2.f, 2.f, 3.f, -3.f, -4.f, -4.f, -4.f, -4.f }), - value, result) -{ - BOOST_TEST(round_half_even(value) == result); -} - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Index2Coord, boost::unit_test::data::make({ TensorShape{ 1U }, TensorShape{ 2U }, TensorShape{ 2U, 3U } }) ^ boost::unit_test::data::make({ 0, 1, 2 }) ^ - boost::unit_test::data::make({ Coordinates{ 0 }, Coordinates{ 1 }, Coordinates{ 0, 1 } }), shape, index, ref_coordinate) -{ - Coordinates coordinate = index2coord(shape, index); - - BOOST_TEST(compare_dimensions(coordinate, ref_coordinate)); -} - -//FIXME: Negative tests only work in debug mode -#if 0 -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Index2CoordFail, boost::unit_test::data::make({ TensorShape{}, TensorShape{ 2U }, TensorShape{ 2U } }) ^ boost::unit_test::data::make({ 0, -1, 2 }), shape, index) -{ - BOOST_CHECK_THROW(index2coord(shape, index), std::runtime_error); -} -#endif /* 0 */ - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Coord2Index, boost::unit_test::data::make({ TensorShape{ 1U }, TensorShape{ 2U }, TensorShape{ 2U, 3U } }) ^ boost::unit_test::data::make({ Coordinates{ 0 }, Coordinates{ 1 }, Coordinates{ 0, 1 } }) - ^ boost::unit_test::data::make({ 0, 1, 2 }), - shape, coordinate, ref_index) -{ - int index = coord2index(shape, coordinate); - - BOOST_TEST(index == ref_index); -} - -//FIXME: Negative tests only work in debug mode -#if 0 -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) -BOOST_DATA_TEST_CASE(Coord2IndexFail, boost::unit_test::data::make({ TensorShape{}, TensorShape{ 2U } }) ^ boost::unit_test::data::make({ Coordinates{ 0 }, Coordinates{} }), shape, coordinate) -{ - BOOST_CHECK_THROW(coord2index(shape, coordinate), std::runtime_error); -} -#endif /* 0 */ - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ diff --git a/tests/validation/Validation.cpp b/tests/validation/Validation.cpp index d321e63d77..fec7c10939 100644 --- a/tests/validation/Validation.cpp +++ b/tests/validation/Validation.cpp @@ -25,22 +25,14 @@ #include "arm_compute/core/Coordinates.h" #include "arm_compute/core/Error.h" -#include "arm_compute/core/FixedPoint.h" -#include "arm_compute/core/IArray.h" #include "arm_compute/core/TensorShape.h" #include "arm_compute/runtime/Tensor.h" -#include "tests/IAccessor.h" -#include "tests/RawTensor.h" -#include "tests/TypePrinter.h" -#include "tests/Utils.h" #include "tests/validation/half.h" #include <array> #include <cmath> #include <cstddef> #include <cstdint> -#include <iomanip> -#include <vector> namespace arm_compute { @@ -99,39 +91,6 @@ double get_double_data(const void *ptr, DataType data_type) } } -bool is_equal(double target, double ref, double max_absolute_error = std::numeric_limits<double>::epsilon(), double max_relative_error = 0.0001f) -{ - if(!std::isfinite(target) || !std::isfinite(ref)) - { - return false; - } - - // No need further check if they are equal - if(ref == target) - { - return true; - } - - // Need this check for the situation when the two values close to zero but have different sign - if(std::abs(std::abs(ref) - std::abs(target)) <= max_absolute_error) - { - return true; - } - - double relative_error = 0; - - if(std::abs(target) > std::abs(ref)) - { - relative_error = std::abs((target - ref) / target); - } - else - { - relative_error = std::abs((ref - target) / ref); - } - - return relative_error <= max_relative_error; -} - void check_border_element(const IAccessor &tensor, const Coordinates &id, const BorderMode &border_mode, const void *border_value, int64_t &num_elements, int64_t &num_mismatches) @@ -142,61 +101,46 @@ void check_border_element(const IAccessor &tensor, const Coordinates &id, if(border_mode == BorderMode::REPLICATE) { Coordinates border_id{ id }; - border_id.set(1, 0); - border_value = tensor(border_id); - } - // Iterate over all channels within one element - for(int channel = 0; channel < tensor.num_channels(); ++channel) - { - const size_t channel_offset = channel * channel_size; - const double target = get_double_data(ptr + channel_offset, tensor.data_type()); - const double ref = get_double_data(static_cast<const uint8_t *>(border_value) + channel_offset, tensor.data_type()); - const bool equal = is_equal(target, ref); - - BOOST_TEST_INFO("id = " << id); - BOOST_TEST_INFO("channel = " << channel); - BOOST_TEST_INFO("reference = " << std::setprecision(5) << ref); - BOOST_TEST_INFO("target = " << std::setprecision(5) << target); - BOOST_TEST_WARN(equal); + if(id.x() < 0) + { + border_id.set(0, 0); + } + else if(static_cast<size_t>(id.x()) >= tensor.shape().x()) + { + border_id.set(0, tensor.shape().x() - 1); + } - if(!equal) + if(id.y() < 0) { - ++num_mismatches; + border_id.set(1, 0); + } + else if(static_cast<size_t>(id.y()) >= tensor.shape().y()) + { + border_id.set(1, tensor.shape().y() - 1); } - ++num_elements; + border_value = tensor(border_id); } -} - -void check_single_element(const Coordinates &id, const IAccessor &tensor, const RawTensor &reference, float tolerance_value, - uint64_t wrap_range, int min_channels, size_t channel_size, int64_t &num_mismatches, int64_t &num_elements) -{ - const auto ptr = static_cast<const uint8_t *>(tensor(id)); - const auto ref_ptr = static_cast<const uint8_t *>(reference(id)); // Iterate over all channels within one element - for(int channel = 0; channel < min_channels; ++channel) + for(int channel = 0; channel < tensor.num_channels(); ++channel) { const size_t channel_offset = channel * channel_size; - const double target = get_double_data(ptr + channel_offset, reference.data_type()); - const double ref = get_double_data(ref_ptr + channel_offset, reference.data_type()); - bool equal = is_equal(target, ref, tolerance_value); + const double target = get_double_data(ptr + channel_offset, tensor.data_type()); + const double reference = get_double_data(static_cast<const uint8_t *>(border_value) + channel_offset, tensor.data_type()); - if(wrap_range != 0 && !equal) + if(!compare<AbsoluteTolerance<double>, double>(target, reference)) { - equal = is_equal(target, ref, wrap_range - tolerance_value); - } + ARM_COMPUTE_TEST_INFO("id = " << id); + ARM_COMPUTE_TEST_INFO("channel = " << channel); + ARM_COMPUTE_TEST_INFO("target = " << std::setprecision(5) << target); + ARM_COMPUTE_TEST_INFO("reference = " << std::setprecision(5) << reference); + ARM_COMPUTE_EXPECT_EQUAL(target, reference, framework::LogLevel::DEBUG); - if(!equal) - { - BOOST_TEST_INFO("id = " << id); - BOOST_TEST_INFO("channel = " << channel); - BOOST_TEST_INFO("reference = " << std::setprecision(5) << ref); - BOOST_TEST_INFO("target = " << std::setprecision(5) << target); - BOOST_TEST_WARN(equal); ++num_mismatches; } + ++num_elements; } } @@ -204,107 +148,31 @@ void check_single_element(const Coordinates &id, const IAccessor &tensor, const void validate(const arm_compute::ValidRegion ®ion, const arm_compute::ValidRegion &reference) { - BOOST_TEST(region.anchor.num_dimensions() == reference.anchor.num_dimensions()); - BOOST_TEST(region.shape.num_dimensions() == reference.shape.num_dimensions()); + ARM_COMPUTE_EXPECT_EQUAL(region.anchor.num_dimensions(), reference.anchor.num_dimensions(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT_EQUAL(region.shape.num_dimensions(), reference.shape.num_dimensions(), framework::LogLevel::ERRORS); for(unsigned int d = 0; d < region.anchor.num_dimensions(); ++d) { - BOOST_TEST(region.anchor[d] == reference.anchor[d]); + ARM_COMPUTE_EXPECT_EQUAL(region.anchor[d], reference.anchor[d], framework::LogLevel::ERRORS); } for(unsigned int d = 0; d < region.shape.num_dimensions(); ++d) { - BOOST_TEST(region.shape[d] == reference.shape[d]); + ARM_COMPUTE_EXPECT_EQUAL(region.shape[d], reference.shape[d], framework::LogLevel::ERRORS); } } void validate(const arm_compute::PaddingSize &padding, const arm_compute::PaddingSize &reference) { - BOOST_TEST(padding.top == reference.top); - BOOST_TEST(padding.right == reference.right); - BOOST_TEST(padding.bottom == reference.bottom); - BOOST_TEST(padding.left == reference.left); -} - -void validate(const IAccessor &tensor, const RawTensor &reference, float tolerance_value, float tolerance_number, uint64_t wrap_range) -{ - // Validate with valid region covering the entire shape - validate(tensor, reference, shape_to_valid_region(tensor.shape()), tolerance_value, tolerance_number, wrap_range); -} - -void validate(const IAccessor &tensor, const RawTensor &reference, const ValidRegion &valid_region, float tolerance_value, float tolerance_number, uint64_t wrap_range) -{ - int64_t num_mismatches = 0; - int64_t num_elements = 0; - - BOOST_TEST(tensor.element_size() == reference.element_size()); - BOOST_TEST(tensor.format() == reference.format()); - BOOST_TEST(tensor.data_type() == reference.data_type()); - BOOST_TEST(tensor.num_channels() == reference.num_channels()); - BOOST_TEST(compare_dimensions(tensor.shape(), reference.shape())); - - const int min_elements = std::min(tensor.num_elements(), reference.num_elements()); - const int min_channels = std::min(tensor.num_channels(), reference.num_channels()); - const size_t channel_size = element_size_from_data_type(reference.data_type()); - - // Iterate over all elements within valid region, e.g. U8, S16, RGB888, ... - for(int element_idx = 0; element_idx < min_elements; ++element_idx) - { - const Coordinates id = index2coord(reference.shape(), element_idx); - if(is_in_valid_region(valid_region, id)) - { - check_single_element(id, tensor, reference, tolerance_value, wrap_range, min_channels, channel_size, num_mismatches, num_elements); - } - } - - const int64_t absolute_tolerance_number = tolerance_number * num_elements; - const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f; - - BOOST_TEST(num_mismatches <= absolute_tolerance_number, - num_mismatches << " values (" << std::setprecision(2) << percent_mismatches - << "%) mismatched (maximum tolerated " << std::setprecision(2) << tolerance_number << "%)"); -} - -void validate(const IAccessor &tensor, const RawTensor &reference, const RawTensor &valid_mask, float tolerance_value, float tolerance_number, uint64_t wrap_range) -{ - int64_t num_mismatches = 0; - int64_t num_elements = 0; - - BOOST_TEST(tensor.element_size() == reference.element_size()); - BOOST_TEST(tensor.format() == reference.format()); - BOOST_TEST(tensor.data_type() == reference.data_type()); - BOOST_TEST(tensor.num_channels() == reference.num_channels()); - BOOST_TEST(compare_dimensions(tensor.shape(), reference.shape())); - - const int min_elements = std::min(tensor.num_elements(), reference.num_elements()); - const int min_channels = std::min(tensor.num_channels(), reference.num_channels()); - const size_t channel_size = element_size_from_data_type(reference.data_type()); - - // Iterate over all elements within valid region, e.g. U8, S16, RGB888, ... - for(int element_idx = 0; element_idx < min_elements; ++element_idx) - { - const Coordinates id = index2coord(reference.shape(), element_idx); - if(valid_mask[element_idx] == 1) - { - check_single_element(id, tensor, reference, tolerance_value, wrap_range, min_channels, channel_size, num_mismatches, num_elements); - } - else - { - ++num_elements; - } - } - - const int64_t absolute_tolerance_number = tolerance_number * num_elements; - const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f; - - BOOST_TEST(num_mismatches <= absolute_tolerance_number, - num_mismatches << " values (" << std::setprecision(2) << percent_mismatches - << "%) mismatched (maximum tolerated " << std::setprecision(2) << tolerance_number << "%)"); + ARM_COMPUTE_EXPECT_EQUAL(padding.top, reference.top, framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT_EQUAL(padding.right, reference.right, framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT_EQUAL(padding.bottom, reference.bottom, framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT_EQUAL(padding.left, reference.left, framework::LogLevel::ERRORS); } void validate(const IAccessor &tensor, const void *reference_value) { - BOOST_TEST_REQUIRE((reference_value != nullptr)); + ARM_COMPUTE_ASSERT(reference_value != nullptr); int64_t num_mismatches = 0; int64_t num_elements = 0; @@ -322,17 +190,16 @@ void validate(const IAccessor &tensor, const void *reference_value) { const size_t channel_offset = channel * channel_size; const double target = get_double_data(ptr + channel_offset, tensor.data_type()); - const double ref = get_double_data(reference_value, tensor.data_type()); - const bool equal = is_equal(target, ref); - - BOOST_TEST_INFO("id = " << id); - BOOST_TEST_INFO("channel = " << channel); - BOOST_TEST_INFO("reference = " << std::setprecision(5) << ref); - BOOST_TEST_INFO("target = " << std::setprecision(5) << target); - BOOST_TEST_WARN(equal); + const double reference = get_double_data(reference_value, tensor.data_type()); - if(!equal) + if(!compare<AbsoluteTolerance<double>, double>(target, reference)) { + ARM_COMPUTE_TEST_INFO("id = " << id); + ARM_COMPUTE_TEST_INFO("channel = " << channel); + ARM_COMPUTE_TEST_INFO("target = " << std::setprecision(5) << target); + ARM_COMPUTE_TEST_INFO("reference = " << std::setprecision(5) << reference); + ARM_COMPUTE_EXPECT_EQUAL(target, reference, framework::LogLevel::DEBUG); + ++num_mismatches; } @@ -340,10 +207,13 @@ void validate(const IAccessor &tensor, const void *reference_value) } } - const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f; + if(num_elements > 0) + { + const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f; - BOOST_TEST(num_mismatches == 0, - num_mismatches << " values (" << std::setprecision(2) << percent_mismatches << "%) mismatched"); + ARM_COMPUTE_TEST_INFO(num_mismatches << " values (" << std::fixed << std::setprecision(2) << percent_mismatches << "%) mismatched"); + ARM_COMPUTE_EXPECT_EQUAL(num_mismatches, 0, framework::LogLevel::ERRORS); + } } void validate(const IAccessor &tensor, BorderSize border_size, const BorderMode &border_mode, const void *border_value) @@ -354,7 +224,7 @@ void validate(const IAccessor &tensor, BorderSize border_size, const BorderMode } else if(border_mode == BorderMode::CONSTANT) { - BOOST_TEST((border_value != nullptr)); + ARM_COMPUTE_ASSERT(border_value != nullptr); } int64_t num_mismatches = 0; @@ -414,63 +284,23 @@ void validate(const IAccessor &tensor, BorderSize border_size, const BorderMode } } - const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f; + if(num_elements > 0) + { + const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f; - BOOST_TEST(num_mismatches == 0, - num_mismatches << " values (" << std::setprecision(2) << percent_mismatches << "%) mismatched"); + ARM_COMPUTE_TEST_INFO(num_mismatches << " values (" << std::fixed << std::setprecision(2) << percent_mismatches << "%) mismatched"); + ARM_COMPUTE_EXPECT_EQUAL(num_mismatches, 0, framework::LogLevel::ERRORS); + } } void validate(std::vector<unsigned int> classified_labels, std::vector<unsigned int> expected_labels) { - ARM_COMPUTE_UNUSED(classified_labels); - ARM_COMPUTE_UNUSED(expected_labels); - BOOST_TEST(expected_labels.size() != 0); - BOOST_TEST(classified_labels.size() == expected_labels.size()); + ARM_COMPUTE_EXPECT_EQUAL(classified_labels.size(), expected_labels.size(), framework::LogLevel::ERRORS); for(unsigned int i = 0; i < expected_labels.size(); ++i) { - BOOST_TEST(classified_labels[i] == expected_labels[i]); - } -} - -void validate(float target, float ref, float tolerance_abs_error, float tolerance_relative_error) -{ - const bool equal = is_equal(target, ref, tolerance_abs_error, tolerance_relative_error); - - BOOST_TEST_INFO("reference = " << std::setprecision(5) << ref); - BOOST_TEST_INFO("target = " << std::setprecision(5) << target); - BOOST_TEST(equal); -} - -void validate(IArray<KeyPoint> &target, IArray<KeyPoint> &ref, int64_t tolerance) -{ - int64_t num_mismatches = 0; - - BOOST_TEST_WARN(target.num_values() == ref.num_values()); - - for(size_t i = 0; i < target.num_values(); ++i) - { - KeyPoint *ref_val = std::find_if(ref.buffer(), ref.buffer() + ref.num_values(), [&target, i](KeyPoint key) - { - return key.x == target.at(i).x && key.y == target.at(i).y; - }); - - const KeyPoint &key = target.at(i); - - if((ref_val == ref.buffer() + ref.num_values()) || !(is_equal(key.strength, ref_val->strength) && is_equal(key.scale, ref_val->scale) && is_equal(key.orientation, ref_val->orientation) - && is_equal(key.tracking_status, ref_val->tracking_status) && is_equal(key.error, ref_val->error))) - { - ++num_mismatches; - - BOOST_TEST_WARN(is_equal(key.strength, ref_val->strength)); - BOOST_TEST_WARN(is_equal(key.scale, ref_val->scale)); - BOOST_TEST_WARN(is_equal(key.orientation, ref_val->orientation)); - BOOST_TEST_WARN(is_equal(key.tracking_status, ref_val->tracking_status)); - BOOST_TEST_WARN(is_equal(key.error, ref_val->error)); - } + ARM_COMPUTE_EXPECT_EQUAL(classified_labels[i], expected_labels[i], framework::LogLevel::ERRORS); } - - BOOST_TEST(num_mismatches <= tolerance); } } // namespace validation } // namespace test diff --git a/tests/validation/Validation.h b/tests/validation/Validation.h index 57013312e1..db95e06058 100644 --- a/tests/validation/Validation.h +++ b/tests/validation/Validation.h @@ -21,44 +21,123 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef __ARM_COMPUTE_TEST_REFERENCE_VALIDATION_H__ -#define __ARM_COMPUTE_TEST_REFERENCE_VALIDATION_H__ +#ifndef __ARM_COMPUTE_TEST_VALIDATION_H__ +#define __ARM_COMPUTE_TEST_VALIDATION_H__ +#include "arm_compute/core/FixedPoint.h" #include "arm_compute/core/Types.h" -#include "arm_compute/runtime/Array.h" -#include "tests/RawTensor.h" - -#include "boost_wrapper.h" +#include "tests/IAccessor.h" +#include "tests/SimpleTensor.h" +#include "tests/TypePrinter.h" +#include "tests/Utils.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Exceptions.h" +#include <iomanip> +#include <ios> #include <vector> namespace arm_compute { -class Tensor; - namespace test { -class IAccessor; - namespace validation { +/** Class reprensenting an absolute tolerance value. */ +template <typename T> +class AbsoluteTolerance +{ +public: + /** Underlying type. */ + using value_type = T; + + /* Default constructor. + * + * Initialises the tolerance to 0. + */ + AbsoluteTolerance() = default; + + /** Constructor. + * + * @param[in] value Absolute tolerance value. + */ + explicit constexpr AbsoluteTolerance(T value) + : _value{ value } + { + } + + /** Implicit conversion to the underlying type. */ + constexpr operator T() const + { + return _value; + } + +private: + T _value{ std::numeric_limits<T>::epsilon() }; +}; + +/** Class reprensenting a relative tolerance value. */ +class RelativeTolerance +{ +public: + /** Underlying type. */ + using value_type = double; + + /* Default constructor. + * + * Initialises the tolerance to 0. + */ + RelativeTolerance() = default; + + /** Constructor. + * + * @param[in] value Relative tolerance value. + */ + explicit constexpr RelativeTolerance(value_type value) + : _value{ value } + { + } + + /** Implicit conversion to the underlying type. */ + constexpr operator value_type() const + { + return _value; + } + +private: + value_type _value{ 0 }; +}; + +/** Print AbsoluteTolerance type. */ +template <typename T> +inline ::std::ostream &operator<<(::std::ostream &os, const AbsoluteTolerance<T> &tolerance) +{ + os << static_cast<typename AbsoluteTolerance<T>::value_type>(tolerance); + + return os; +} + +/** Print RelativeTolerance type. */ +inline ::std::ostream &operator<<(::std::ostream &os, const RelativeTolerance &tolerance) +{ + os << static_cast<typename RelativeTolerance::value_type>(tolerance); + + return os; +} + template <typename T> -boost::test_tools::predicate_result compare_dimensions(const Dimensions<T> &dimensions1, const Dimensions<T> &dimensions2) +bool compare_dimensions(const Dimensions<T> &dimensions1, const Dimensions<T> &dimensions2) { if(dimensions1.num_dimensions() != dimensions2.num_dimensions()) { - boost::test_tools::predicate_result result(false); - result.message() << "Different dimensionality [" << dimensions1.num_dimensions() << "!=" << dimensions2.num_dimensions() << "]"; - return result; + return false; } for(unsigned int i = 0; i < dimensions1.num_dimensions(); ++i) { if(dimensions1[i] != dimensions2[i]) { - boost::test_tools::predicate_result result(false); - result.message() << "Mismatch in dimension " << i << " [" << dimensions1[i] << "!=" << dimensions2[i] << "]"; - return result; + return false; } } @@ -89,7 +168,8 @@ void validate(const arm_compute::PaddingSize &padding, const arm_compute::Paddin * reference tensor and test tensor is multiple of wrap_range), but such errors would be detected by * other test cases. */ -void validate(const IAccessor &tensor, const RawTensor &reference, float tolerance_value = 0.f, float tolerance_number = 0.f, uint64_t wrap_range = 0); +template <typename T, typename U = AbsoluteTolerance<T>> +void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, U tolerance_value = U(), float tolerance_number = 0.f); /** Validate tensors with valid region. * @@ -101,19 +181,8 @@ void validate(const IAccessor &tensor, const RawTensor &reference, float toleran * reference tensor and test tensor is multiple of wrap_range), but such errors would be detected by * other test cases. */ -void validate(const IAccessor &tensor, const RawTensor &reference, const ValidRegion &valid_region, float tolerance_value = 0.f, float tolerance_number = 0.f, uint64_t wrap_range = 0); - -/** Validate tensors with valid mask. - * - * - Dimensionality has to be the same. - * - All values have to match. - * - * @note: wrap_range allows cases where reference tensor rounds up to the wrapping point, causing it to wrap around to - * zero while the test tensor stays at wrapping point to pass. This may permit true erroneous cases (difference between - * reference tensor and test tensor is multiple of wrap_range), but such errors would be detected by - * other test cases. - */ -void validate(const IAccessor &tensor, const RawTensor &reference, const RawTensor &valid_mask, float tolerance_value = 0.f, float tolerance_number = 0.f, uint64_t wrap_range = 0); +template <typename T, typename U = AbsoluteTolerance<T>> +void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, const ValidRegion &valid_region, U tolerance_value = U(), float tolerance_number = 0.f); /** Validate tensors against constant value. * @@ -139,54 +208,143 @@ void validate(std::vector<unsigned int> classified_labels, std::vector<unsigned * * - All values should match */ -void validate(float target, float ref, float tolerance_abs_error = std::numeric_limits<float>::epsilon(), float tolerance_relative_error = 0.0001f); +template <typename T, typename U> +void validate(T target, T reference, U tolerance = AbsoluteTolerance<T>()); -/** Validate min max location. - * - * - All values should match - */ template <typename T> -void validate_min_max_loc(T min, T ref_min, T max, T ref_max, - IArray<Coordinates2D> &min_loc, IArray<Coordinates2D> &ref_min_loc, IArray<Coordinates2D> &max_loc, IArray<Coordinates2D> &ref_max_loc, - uint32_t min_count, uint32_t ref_min_count, uint32_t max_count, uint32_t ref_max_count) +struct compare_base { - BOOST_TEST(min == ref_min); - BOOST_TEST(max == ref_max); + compare_base(typename T::value_type target, typename T::value_type reference, T tolerance = T(0)) + : _target{ target }, _reference{ reference }, _tolerance{ tolerance } + { + } + + typename T::value_type _target{}; + typename T::value_type _reference{}; + T _tolerance{}; +}; - BOOST_TEST(min_count == min_loc.num_values()); - BOOST_TEST(max_count == max_loc.num_values()); - BOOST_TEST(ref_min_count == ref_min_loc.num_values()); - BOOST_TEST(ref_max_count == ref_max_loc.num_values()); +template <typename T, typename U> +struct compare; - BOOST_TEST(min_count == ref_min_count); - BOOST_TEST(max_count == ref_max_count); +template <typename U> +struct compare<AbsoluteTolerance<U>, U> : public compare_base<AbsoluteTolerance<U>> +{ + using compare_base<AbsoluteTolerance<U>>::compare_base; - for(uint32_t i = 0; i < min_count; i++) + operator bool() const { - Coordinates2D *same_coords = std::find_if(ref_min_loc.buffer(), ref_min_loc.buffer() + min_count, [&min_loc, i](Coordinates2D coord) + if(!std::isfinite(this->_target) || !std::isfinite(this->_reference)) { - return coord.x == min_loc.at(i).x && coord.y == min_loc.at(i).y; - }); + return false; + } + else if(this->_target == this->_reference) + { + return true; + } - BOOST_TEST(same_coords != ref_min_loc.buffer() + min_count); + return static_cast<U>(std::abs(this->_target - this->_reference)) <= static_cast<U>(this->_tolerance); } +}; + +template <typename U> +struct compare<RelativeTolerance, U> : public compare_base<RelativeTolerance> +{ + using compare_base<RelativeTolerance>::compare_base; - for(uint32_t i = 0; i < max_count; i++) + operator bool() const { - Coordinates2D *same_coords = std::find_if(ref_max_loc.buffer(), ref_max_loc.buffer() + max_count, [&max_loc, i](Coordinates2D coord) + if(!std::isfinite(_target) || !std::isfinite(_reference)) { - return coord.x == max_loc.at(i).x && coord.y == max_loc.at(i).y; - }); + return false; + } + else if(_target == _reference) + { + return true; + } - BOOST_TEST(same_coords != ref_max_loc.buffer() + max_count); + const double relative_change = std::abs(static_cast<double>(_target - _reference)) / _reference; + + return relative_change <= _tolerance; } +}; + +template <typename T, typename U> +void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, U tolerance_value, float tolerance_number) +{ + // Validate with valid region covering the entire shape + validate(tensor, reference, shape_to_valid_region(tensor.shape()), tolerance_value, tolerance_number); } -/** Validate KeyPoint arrays. - * - * - All values should match - */ -void validate(IArray<KeyPoint> &target, IArray<KeyPoint> &ref, int64_t tolerance = 0); +template <typename T, typename U> +void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, const ValidRegion &valid_region, U tolerance_value, float tolerance_number) +{ + int64_t num_mismatches = 0; + int64_t num_elements = 0; + + ARM_COMPUTE_EXPECT_EQUAL(tensor.element_size(), reference.element_size(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT_EQUAL(tensor.data_type(), reference.data_type(), framework::LogLevel::ERRORS); + + if(reference.format() != Format::UNKNOWN) + { + ARM_COMPUTE_EXPECT_EQUAL(tensor.format(), reference.format(), framework::LogLevel::ERRORS); + } + + ARM_COMPUTE_EXPECT_EQUAL(tensor.num_channels(), reference.num_channels(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(compare_dimensions(tensor.shape(), reference.shape()), framework::LogLevel::ERRORS); + + const int min_elements = std::min(tensor.num_elements(), reference.num_elements()); + const int min_channels = std::min(tensor.num_channels(), reference.num_channels()); + + // Iterate over all elements within valid region, e.g. U8, S16, RGB888, ... + for(int element_idx = 0; element_idx < min_elements; ++element_idx) + { + const Coordinates id = index2coord(reference.shape(), element_idx); + + if(is_in_valid_region(valid_region, id)) + { + // Iterate over all channels within one element + for(int c = 0; c < min_channels; ++c) + { + const T &target_value = reinterpret_cast<const T *>(tensor(id))[c]; + const T &reference_value = reinterpret_cast<const T *>(reference(id))[c]; + + if(!compare<U, typename U::value_type>(target_value, reference_value, tolerance_value)) + { + ARM_COMPUTE_TEST_INFO("id = " << id); + ARM_COMPUTE_TEST_INFO("channel = " << c); + ARM_COMPUTE_TEST_INFO("target = " << std::setprecision(5) << framework::make_printable(target_value)); + ARM_COMPUTE_TEST_INFO("reference = " << std::setprecision(5) << framework::make_printable(reference_value)); + ARM_COMPUTE_TEST_INFO("tolerance = " << std::setprecision(5) << framework::make_printable(static_cast<typename U::value_type>(tolerance_value))); + ARM_COMPUTE_EXPECT_EQUAL(target_value, reference_value, framework::LogLevel::DEBUG); + + ++num_mismatches; + } + + ++num_elements; + } + } + } + + if(num_elements > 0) + { + const int64_t absolute_tolerance_number = tolerance_number * num_elements; + const float percent_mismatches = static_cast<float>(num_mismatches) / num_elements * 100.f; + + ARM_COMPUTE_TEST_INFO(num_mismatches << " values (" << std::fixed << std::setprecision(2) << percent_mismatches + << "%) mismatched (maximum tolerated " << std::setprecision(2) << tolerance_number << "%)"); + ARM_COMPUTE_EXPECT(num_mismatches <= absolute_tolerance_number, framework::LogLevel::ERRORS); + } +} + +template <typename T, typename U> +void validate(T target, T reference, U tolerance) +{ + ARM_COMPUTE_TEST_INFO("reference = " << std::setprecision(5) << framework::make_printable(reference)); + ARM_COMPUTE_TEST_INFO("target = " << std::setprecision(5) << framework::make_printable(target)); + ARM_COMPUTE_TEST_INFO("tolerance = " << std::setprecision(5) << framework::make_printable(static_cast<typename U::value_type>(tolerance))); + ARM_COMPUTE_EXPECT((compare<U, typename U::value_type>(target, reference, tolerance)), framework::LogLevel::ERRORS); +} } // namespace validation } // namespace test } // namespace arm_compute diff --git a/tests/validation/fixtures/ActivationLayerFixture.h b/tests/validation/fixtures/ActivationLayerFixture.h new file mode 100644 index 0000000000..384e63bf49 --- /dev/null +++ b/tests/validation/fixtures/ActivationLayerFixture.h @@ -0,0 +1,157 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_ACTIVATION_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_ACTIVATION_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/ActivationLayer.h" +#include "tests/validation/Helpers.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class ActivationValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, bool in_place, ActivationLayerInfo::ActivationFunction function, float alpha_beta, DataType data_type, int fractional_bits) + { + _fractional_bits = fractional_bits; + _data_type = data_type; + _function = function; + + ActivationLayerInfo info(function, alpha_beta, alpha_beta); + + _target = compute_target(shape, in_place, info, data_type, fractional_bits); + _reference = compute_reference(shape, info, data_type, fractional_bits); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + if(is_data_type_float(_data_type)) + { + float min_bound = 0; + float max_bound = 0; + std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<T>(_function, _data_type); + std::uniform_real_distribution<> distribution(min_bound, max_bound); + library->fill(tensor, distribution, 0); + } + else + { + int min_bound = 0; + int max_bound = 0; + std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<T>(_function, _data_type, _fractional_bits); + std::uniform_int_distribution<> distribution(min_bound, max_bound); + library->fill(tensor, distribution, 0); + } + } + + TensorType compute_target(const TensorShape &shape, bool in_place, ActivationLayerInfo info, DataType data_type, int fixed_point_position = 0) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position); + TensorType dst = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position); + + // Create and configure function + FunctionType act_layer; + + TensorType *dst_ptr = in_place ? &src : &dst; + + act_layer.configure(&src, dst_ptr, info); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + + if(!in_place) + { + dst.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + } + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + act_layer.run(); + + if(in_place) + { + return src; + } + else + { + return dst; + } + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, ActivationLayerInfo info, DataType data_type, int fixed_point_position = 0) + { + // Create reference + SimpleTensor<T> src{ shape, data_type, 1, fixed_point_position }; + + // Fill reference + fill(src); + + return reference::activation_layer<T>(src, info); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + int _fractional_bits{}; + DataType _data_type{}; + ActivationLayerInfo::ActivationFunction _function{}; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class ActivationValidationFixture : public ActivationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape shape, bool in_place, ActivationLayerInfo::ActivationFunction function, float alpha_beta, DataType data_type) + { + ActivationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, in_place, function, alpha_beta, data_type, 0); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_ACTIVATION_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/BitwiseAndFixture.h b/tests/validation/fixtures/BitwiseAndFixture.h new file mode 100644 index 0000000000..0dfff868ab --- /dev/null +++ b/tests/validation/fixtures/BitwiseAndFixture.h @@ -0,0 +1,113 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_BITWISE_AND_FIXTURE +#define ARM_COMPUTE_TEST_BITWISE_AND_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/BitwiseAnd.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class BitwiseAndValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + _target = compute_target(shape, data_type); + _reference = compute_reference(shape, data_type); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + library->fill_tensor_uniform(tensor, i); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type) + { + // Create tensors + TensorType src1 = create_tensor<TensorType>(shape, data_type); + TensorType src2 = create_tensor<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(shape, data_type); + + // Create and configure function + FunctionType bitwise_and; + + bitwise_and.configure(&src1, &src2, &dst); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src1.allocator()->allocate(); + src2.allocator()->allocate(); + dst.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src1), 0); + fill(AccessorType(src2), 1); + + // Compute function + bitwise_and.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type) + { + // Create reference + SimpleTensor<T> src1{ shape, data_type }; + SimpleTensor<T> src2{ shape, data_type }; + + // Fill reference + fill(src1, 0); + fill(src2, 1); + + return reference::bitwise_and<T>(src1, src2); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_BITWISE_AND_FIXTURE */ diff --git a/tests/validation/fixtures/BitwiseNotFixture.h b/tests/validation/fixtures/BitwiseNotFixture.h new file mode 100644 index 0000000000..e5bf69992e --- /dev/null +++ b/tests/validation/fixtures/BitwiseNotFixture.h @@ -0,0 +1,106 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_BITWISE_NOT_FIXTURE +#define ARM_COMPUTE_TEST_BITWISE_NOT_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/BitwiseNot.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class BitwiseNotValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + _target = compute_target(shape, data_type); + _reference = compute_reference(shape, data_type); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(shape, data_type); + + // Create and configure function + FunctionType bitwise_not; + + bitwise_not.configure(&src, &dst); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + bitwise_not.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type) + { + // Create reference + SimpleTensor<T> src{ shape, data_type }; + + // Fill reference + fill(src); + + return reference::bitwise_not<T>(src); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_BITWISE_NOT_FIXTURE */ diff --git a/tests/validation/fixtures/BitwiseOrFixture.h b/tests/validation/fixtures/BitwiseOrFixture.h new file mode 100644 index 0000000000..d61e767bf3 --- /dev/null +++ b/tests/validation/fixtures/BitwiseOrFixture.h @@ -0,0 +1,113 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_BITWISE_OR_FIXTURE +#define ARM_COMPUTE_TEST_BITWISE_OR_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/BitwiseOr.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class BitwiseOrValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + _target = compute_target(shape, data_type); + _reference = compute_reference(shape, data_type); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + library->fill_tensor_uniform(tensor, i); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type) + { + // Create tensors + TensorType src1 = create_tensor<TensorType>(shape, data_type); + TensorType src2 = create_tensor<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(shape, data_type); + + // Create and configure function + FunctionType bitwise_or; + + bitwise_or.configure(&src1, &src2, &dst); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src1.allocator()->allocate(); + src2.allocator()->allocate(); + dst.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src1), 0); + fill(AccessorType(src2), 1); + + // Compute function + bitwise_or.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type) + { + // Create reference + SimpleTensor<T> src1{ shape, data_type }; + SimpleTensor<T> src2{ shape, data_type }; + + // Fill reference + fill(src1, 0); + fill(src2, 1); + + return reference::bitwise_or<T>(src1, src2); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_BITWISE_OR_FIXTURE */ diff --git a/tests/validation/fixtures/BitwiseXorFixture.h b/tests/validation/fixtures/BitwiseXorFixture.h new file mode 100644 index 0000000000..16fa8c0422 --- /dev/null +++ b/tests/validation/fixtures/BitwiseXorFixture.h @@ -0,0 +1,113 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_BITWISE_XOR_FIXTURE +#define ARM_COMPUTE_TEST_BITWISE_XOR_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/BitwiseXor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class BitwiseXorValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + _target = compute_target(shape, data_type); + _reference = compute_reference(shape, data_type); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + library->fill_tensor_uniform(tensor, i); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type) + { + // Create tensors + TensorType src1 = create_tensor<TensorType>(shape, data_type); + TensorType src2 = create_tensor<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(shape, data_type); + + // Create and configure function + FunctionType bitwise_xor; + + bitwise_xor.configure(&src1, &src2, &dst); + + ARM_COMPUTE_EXPECT(src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src1.allocator()->allocate(); + src2.allocator()->allocate(); + dst.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src1.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!src2.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src1), 0); + fill(AccessorType(src2), 1); + + // Compute function + bitwise_xor.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type) + { + // Create reference + SimpleTensor<T> src1{ shape, data_type }; + SimpleTensor<T> src2{ shape, data_type }; + + // Fill reference + fill(src1, 0); + fill(src2, 1); + + return reference::bitwise_xor<T>(src1, src2); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_BITWISE_XOR_FIXTURE */ diff --git a/tests/validation/fixtures/ConvolutionLayerFixture.h b/tests/validation/fixtures/ConvolutionLayerFixture.h new file mode 100644 index 0000000000..87b11ac130 --- /dev/null +++ b/tests/validation/fixtures/ConvolutionLayerFixture.h @@ -0,0 +1,152 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_CONVOLUTION_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_CONVOLUTION_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/ConvolutionLayer.h" +#include "tests/validation/Helpers.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class ConvolutionValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, DataType data_type, int fractional_bits) + { + _fractional_bits = fractional_bits; + _data_type = data_type; + + _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, fractional_bits); + _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, fractional_bits); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + switch(tensor.data_type()) + { + case DataType::F16: + case DataType::F32: + { + std::uniform_real_distribution<> distribution(-1.0f, 1.0f); + library->fill(tensor, distribution, i); + break; + } + default: + library->fill_tensor_uniform(tensor, i); + } + } + + TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info, + DataType data_type, int fixed_point_position) + { + // Create tensors + TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, fixed_point_position); + TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1, fixed_point_position); + TensorType bias = create_tensor<TensorType>(bias_shape, data_type, 1, fixed_point_position); + TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, fixed_point_position); + + // Create and configure function + FunctionType conv; + conv.configure(&src, &weights, &bias, &dst, info); + + 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); + + // Allocate tensors + src.allocator()->allocate(); + weights.allocator()->allocate(); + bias.allocator()->allocate(); + dst.allocator()->allocate(); + + 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); + + // Fill tensors + fill(AccessorType(src), 0); + fill(AccessorType(weights), 1); + fill(AccessorType(bias), 2); + + // Compute NEConvolutionLayer function + conv.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info, + DataType data_type, int fixed_point_position) + { + // Create reference + SimpleTensor<T> src{ input_shape, data_type, 1, fixed_point_position }; + SimpleTensor<T> weights{ weights_shape, data_type, 1, fixed_point_position }; + SimpleTensor<T> bias{ bias_shape, data_type, 1, fixed_point_position }; + + // Fill reference + fill(src, 0); + fill(weights, 1); + fill(bias, 2); + + return reference::convolution_layer<T>(src, weights, bias, output_shape, info); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + int _fractional_bits{}; + DataType _data_type{}; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class ConvolutionValidationFixture : public ConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, DataType data_type) + { + ConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, 0); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_CONVOLUTION_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/DepthConcatenateLayerFixture.h b/tests/validation/fixtures/DepthConcatenateLayerFixture.h new file mode 100644 index 0000000000..2a2e96e821 --- /dev/null +++ b/tests/validation/fixtures/DepthConcatenateLayerFixture.h @@ -0,0 +1,177 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/DepthConcatenateLayer.h" +#include "tests/validation/Helpers.h" + +#include <random> + +namespace arm_compute +{ +class ITensor; +class Tensor; +class ICLTensor; +class CLTensor; + +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class DepthConcatenateValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + // Create input shapes + std::mt19937 gen(library->seed()); + std::uniform_int_distribution<> num_dis(2, 6); + const int num_tensors = num_dis(gen); + + std::vector<TensorShape> shapes(num_tensors, shape); + std::uniform_int_distribution<> depth_dis(1, 7); + std::bernoulli_distribution mutate_dis(0.25f); + std::uniform_real_distribution<> change_dis(-0.25f, 0.f); + + // Generate more shapes based on the input + for(auto &s : shapes) + { + // Set the depth of the tensor + s.set(2, depth_dis(gen)); + + // Randomly change the first dimension + if(mutate_dis(gen)) + { + // Decrease the dimension by a small percentage. Don't increase + // as that could make tensor too large. Also the change must be + // an even number. Otherwise out depth concatenate fails. + s.set(0, s[0] + 2 * static_cast<int>(s[0] * change_dis(gen))); + } + + // Repeat the same as above for the second dimension + if(mutate_dis(gen)) + { + s.set(1, s[1] + 2 * static_cast<int>(s[1] * change_dis(gen))); + } + } + + _target = compute_target(shapes, data_type); + _reference = compute_reference(shapes, data_type); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + library->fill_tensor_uniform(tensor, i); + } + + TensorType compute_target(std::vector<TensorShape> shapes, DataType data_type) + { + using ITensorType = typename std::conditional<std::is_same<TensorType, Tensor>::value, ITensor, ICLTensor>::type; + + std::vector<TensorType> srcs; + std::vector<ITensorType *> src_ptrs; + + // Create tensors + srcs.reserve(shapes.size()); + + for(const auto &shape : shapes) + { + srcs.emplace_back(create_tensor<TensorType>(shape, data_type, 1, _fractional_bits)); + src_ptrs.emplace_back(&srcs.back()); + } + + TensorShape dst_shape = calculate_depth_concatenate_shape(shapes); + TensorType dst = create_tensor<TensorType>(dst_shape, data_type, 1, _fractional_bits); + + // Create and configure function + FunctionType depth_concat; + depth_concat.configure(src_ptrs, &dst); + + for(auto &src : srcs) + { + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + } + + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + for(auto &src : srcs) + { + src.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + } + + dst.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + int i = 0; + for(auto &src : srcs) + { + fill(AccessorType(src), i++); + } + + // Compute function + depth_concat.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(std::vector<TensorShape> shapes, DataType data_type) + { + std::vector<SimpleTensor<T>> srcs; + + // Create and fill tensors + int i = 0; + for(const auto &shape : shapes) + { + srcs.emplace_back(shape, data_type, 1, _fractional_bits); + fill(srcs.back(), i++); + } + + return reference::depthconcatenate_layer<T>(srcs); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + +private: + int _fractional_bits{ 1 }; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/DepthwiseConvolutionFixture.h b/tests/validation/fixtures/DepthwiseConvolutionFixture.h new file mode 100644 index 0000000000..462c0f888c --- /dev/null +++ b/tests/validation/fixtures/DepthwiseConvolutionFixture.h @@ -0,0 +1,120 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE +#define ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/DepthwiseConvolution.h" +#include "tests/validation/Helpers.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class DepthwiseConvolutionValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape in_shape, TensorShape weights_shape, TensorShape out_shape, PadStrideInfo pad_stride_info) + { + _target = compute_target(in_shape, weights_shape, out_shape, pad_stride_info); + _reference = compute_reference(in_shape, weights_shape, out_shape, pad_stride_info); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + switch(tensor.data_type()) + { + case DataType::F32: + { + std::uniform_real_distribution<> distribution(-1.0f, 1.0f); + library->fill(tensor, distribution, i); + break; + } + default: + library->fill_tensor_uniform(tensor, i); + } + } + + TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &output_shape, PadStrideInfo &pad_stride_info) + { + // Create tensors + TensorType src = create_tensor<TensorType>(input_shape, DataType::F32); + TensorType weights = create_tensor<TensorType>(weights_shape, DataType::F32); + TensorType dst = create_tensor<TensorType>(output_shape, DataType::F32); + + // Create Depthwise Convolution configure function + CLDepthwiseConvolution depthwise_convolution; + depthwise_convolution.configure(&src, &dst, &weights, pad_stride_info); + + // Allocate tensors + src.allocator()->allocate(); + weights.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!weights.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src), 0); + fill(AccessorType(weights), 1); + + // Compute function + depthwise_convolution.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &in_shape, const TensorShape &weights_shape, const TensorShape &out_shape, const PadStrideInfo &pad_stride_info) + { + SimpleTensor<T> src(in_shape, DataType::F32); + SimpleTensor<T> weights(weights_shape, DataType::F32); + + fill(src, 0); + fill(weights, 1); + + return reference::depthwise_convolution(src, weights, out_shape, pad_stride_info); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE */ diff --git a/tests/validation/fixtures/DepthwiseSeparableConvolutionLayerFixture.h b/tests/validation/fixtures/DepthwiseSeparableConvolutionLayerFixture.h new file mode 100644 index 0000000000..e8f6854b49 --- /dev/null +++ b/tests/validation/fixtures/DepthwiseSeparableConvolutionLayerFixture.h @@ -0,0 +1,139 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/DepthwiseSeparableConvolutionLayer.h" +#include "tests/validation/Helpers.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class DepthwiseSeparableConvolutionValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape in_shape, TensorShape depthwise_weights_shape, TensorShape depthwise_out_shape, TensorShape pointwise_weights_shape, TensorShape biases_shape, TensorShape output_shape, + PadStrideInfo pad_stride_depthwise_info, PadStrideInfo pad_stride_pointwise_info) + { + _target = compute_target(in_shape, depthwise_weights_shape, depthwise_out_shape, pointwise_weights_shape, biases_shape, output_shape, pad_stride_depthwise_info, pad_stride_pointwise_info); + _reference = compute_reference(in_shape, depthwise_weights_shape, depthwise_out_shape, pointwise_weights_shape, biases_shape, output_shape, pad_stride_depthwise_info, pad_stride_pointwise_info); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + switch(tensor.data_type()) + { + case DataType::F32: + { + std::uniform_real_distribution<> distribution(-1.0f, 1.0f); + library->fill(tensor, distribution, i); + break; + } + default: + library->fill_tensor_uniform(tensor, i); + } + } + + TensorType compute_target(const TensorShape &input_shape, const TensorShape &depthwise_weights_shape, const TensorShape &depthwise_out_shape, const TensorShape &pointwise_weights_shape, + const TensorShape &biases_shape, + const TensorShape &output_shape, const PadStrideInfo &pad_stride_depthwise_info, const PadStrideInfo &pad_stride_pointwise_info) + { + // Create tensors + TensorType src = create_tensor<TensorType>(input_shape, DataType::F32); + TensorType depthwise_weights = create_tensor<TensorType>(depthwise_weights_shape, DataType::F32); + TensorType depthwise_out = create_tensor<TensorType>(depthwise_out_shape, DataType::F32); + TensorType pointwise_weights = create_tensor<TensorType>(pointwise_weights_shape, DataType::F32); + TensorType biases = create_tensor<TensorType>(biases_shape, DataType::F32); + TensorType dst = create_tensor<TensorType>(output_shape, DataType::F32); + + // Create Depthwise Separable Convolution Layer configure function + CLDepthwiseSeparableConvolutionLayer depthwise_separable_convolution_layer; + depthwise_separable_convolution_layer.configure(&src, &depthwise_weights, &depthwise_out, &pointwise_weights, &biases, &dst, pad_stride_depthwise_info, pad_stride_pointwise_info); + + // Allocate tensors + src.allocator()->allocate(); + depthwise_weights.allocator()->allocate(); + depthwise_out.allocator()->allocate(); + pointwise_weights.allocator()->allocate(); + biases.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!depthwise_weights.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!depthwise_out.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!pointwise_weights.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!biases.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src), 0); + fill(AccessorType(depthwise_weights), 1); + fill(AccessorType(pointwise_weights), 2); + fill(AccessorType(biases), 3); + + // Compute function + depthwise_separable_convolution_layer.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &in_shape, const TensorShape &depthwise_weights_shape, const TensorShape &depthwise_out_shape, const TensorShape &pointwise_weights_shape, + const TensorShape &biases_shape, const TensorShape &dst_shape, const PadStrideInfo &pad_stride_depthwise_info, const PadStrideInfo &pad_stride_pointwise_info) + { + SimpleTensor<T> src(in_shape, DataType::F32); + SimpleTensor<T> depthwise_weights(depthwise_weights_shape, DataType::F32); + SimpleTensor<T> pointwise_weights(pointwise_weights_shape, DataType::F32); + SimpleTensor<T> biases(biases_shape, DataType::F32); + + fill(src, 0); + fill(depthwise_weights, 1); + fill(pointwise_weights, 2); + fill(biases, 3); + + return reference::depthwise_separable_convolution_layer(src, depthwise_weights, depthwise_out_shape, pointwise_weights, biases, dst_shape, pad_stride_depthwise_info, pad_stride_pointwise_info); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/DequantizationLayerFixture.h b/tests/validation/fixtures/DequantizationLayerFixture.h new file mode 100644 index 0000000000..7543eb2d2e --- /dev/null +++ b/tests/validation/fixtures/DequantizationLayerFixture.h @@ -0,0 +1,147 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/DequantizationLayer.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class DequantizationValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + // Initialize random min and max values + rand_min_max(&_min, &_max); + + _target = compute_target(shape, data_type, _min, _max); + _reference = compute_reference(shape, data_type, _min, _max); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type, float min, float max) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(shape, DataType::F32); + + // Create and configure function + FunctionType dequantization_layer; + dequantization_layer.configure(&src, &dst, &min, &max); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + dequantization_layer.run(); + + return dst; + } + + SimpleTensor<float> compute_reference(const TensorShape &shape, DataType data_type, float min, float max) + { + // Create reference + SimpleTensor<T> src{ shape, data_type }; + + // Fill reference + fill(src); + + return reference::dequantization_layer<T>(src, min, max); + } + + /** Generate random constant values to be used as min and max for dequantization. + */ + void rand_min_max(float *min, float *max) + { + std::mt19937 gen(library->seed()); + std::uniform_real_distribution<float> distribution(-10000.0, 10000.0); + + const float n1 = distribution(gen); + const float n2 = distribution(gen); + + if(n1 < n2) + { + *min = n1; + *max = n2; + } + else + { + *min = n2; + *max = n1; + } + } + + TensorType _target{}; + SimpleTensor<float> _reference{}; + float _min = 0.f; + float _max = 0.f; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class DequantizationValidationFixture : public DequantizationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + DequantizationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, data_type); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/DirectConvolutionLayerFixture.h b/tests/validation/fixtures/DirectConvolutionLayerFixture.h new file mode 100644 index 0000000000..6ffebce108 --- /dev/null +++ b/tests/validation/fixtures/DirectConvolutionLayerFixture.h @@ -0,0 +1,86 @@ +/* + * 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 "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/ConvolutionLayer.h" +#include "tests/validation/Helpers.h" +#include "tests/validation/fixtures/ConvolutionLayerFixture.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class DirectConvolutionValidationFixedPointFixture : public ConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape input_shape, int stride_x, int stride_y, int pad_x, int pad_y, unsigned int kernel_size, unsigned int num_kernels, DataType data_type, int fractional_bits) + { + const TensorShape weights_shape(kernel_size, kernel_size, input_shape.z(), num_kernels); + const TensorShape bias_shape(num_kernels); + const PadStrideInfo info(stride_x, stride_y, pad_x, pad_y, DimensionRoundingType::FLOOR); + const TensorShape output_shape = get_output_shape(input_shape, weights_shape, info); + + ConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, fractional_bits); + } + +private: + TensorShape get_output_shape(TensorShape in_shape, TensorShape kernel_shape, const PadStrideInfo &info) + { + TensorShape out_shape(in_shape); + const std::pair<unsigned int, unsigned int> scaled_dims = scaled_dimensions(in_shape.x(), + in_shape.y(), + kernel_shape.x(), + kernel_shape.y(), + info); + out_shape.set(0, scaled_dims.first); + out_shape.set(1, scaled_dims.second); + out_shape.set(2, kernel_shape[3]); + return out_shape; + } +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class DirectConvolutionValidationFixture : public DirectConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape input_shape, int stride_x, int stride_y, int pad_x, int pad_y, unsigned int kernel_size, unsigned int num_kernels, DataType data_type) + { + DirectConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, stride_x, stride_y, pad_x, pad_y, kernel_size, num_kernels, data_type, 0); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/fixtures/FloorFixture.h b/tests/validation/fixtures/FloorFixture.h new file mode 100644 index 0000000000..3f948412af --- /dev/null +++ b/tests/validation/fixtures/FloorFixture.h @@ -0,0 +1,107 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_FLOOR_FIXTURE +#define ARM_COMPUTE_TEST_FLOOR_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/Floor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class FloorValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + _target = compute_target(shape, data_type); + _reference = compute_reference(shape, data_type); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(shape, data_type); + + // Create and configure function + FunctionType floor_func; + floor_func.configure(&src, &dst); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + floor_func.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type) + { + // Create reference + SimpleTensor<T> src{ shape, data_type }; + + // Fill reference + fill(src); + + return reference::floor_layer<T>(src); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_FLOOR_FIXTURE */ diff --git a/tests/validation/fixtures/FullyConnectedLayerFixture.h b/tests/validation/fixtures/FullyConnectedLayerFixture.h new file mode 100644 index 0000000000..d4d68f1af8 --- /dev/null +++ b/tests/validation/fixtures/FullyConnectedLayerFixture.h @@ -0,0 +1,250 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/core/Utils.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/RawTensor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/FullyConnectedLayer.h" +#include "tests/validation/Helpers.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +RawTensor transpose(const RawTensor &src, int interleave = 1) +{ + // Create reference + TensorShape dst_shape(src.shape()); + dst_shape.set(0, src.shape().y() * interleave); + dst_shape.set(1, std::ceil(src.shape().x() / static_cast<float>(interleave))); + + RawTensor dst{ dst_shape, src.data_type() }; + + // Compute reference + uint8_t *out_ptr = dst.data(); + + for(int i = 0; i < dst.num_elements(); i += interleave) + { + Coordinates coord = index2coord(dst.shape(), i); + size_t coord_x = coord.x(); + coord.set(0, coord.y() * interleave); + coord.set(1, coord_x / interleave); + + const int num_elements = std::min<int>(interleave, src.shape().x() - coord.x()); + + std::copy_n(static_cast<const uint8_t *>(src(coord)), num_elements * src.element_size(), out_ptr); + + out_ptr += interleave * dst.element_size(); + } + + return dst; +} +} // namespace + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool run_interleave> +class FullyConnectedLayerValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, bool transpose_weights, bool reshape_weights, DataType data_type, int fractional_bits) + { + ARM_COMPUTE_UNUSED(weights_shape); + ARM_COMPUTE_UNUSED(bias_shape); + + _fractional_bits = fractional_bits; + _data_type = data_type; + + _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, transpose_weights, reshape_weights, data_type, fractional_bits); + _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, transpose_weights, reshape_weights, data_type, fractional_bits); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + if(is_data_type_float(_data_type)) + { + std::uniform_real_distribution<> distribution(0.5f, 1.f); + library->fill(tensor, distribution, i); + } + else + { + library->fill_tensor_uniform(tensor, i); + } + } + + TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, bool transpose_weights, + bool reshape_weights, DataType data_type, int fixed_point_position) + { + TensorShape reshaped_weights_shape(weights_shape); + + // Test actions depending on the target settings + // + // | reshape | !reshape + // -----------+-----------+--------------------------- + // transpose | | *** + // -----------+-----------+--------------------------- + // !transpose | transpose | transpose & + // | | transpose1xW (if required) + // + // ***: That combination is invalid. But we can ignore the transpose flag and handle all !reshape the same + if(!reshape_weights || !transpose_weights) + { + const size_t shape_x = reshaped_weights_shape.x(); + reshaped_weights_shape.set(0, reshaped_weights_shape.y()); + reshaped_weights_shape.set(1, shape_x); + + // Weights have to be passed reshaped + // Transpose 1xW for batched version + if(!reshape_weights && output_shape.y() > 1 && run_interleave) + { + const int transpose_width = 16 / data_size_from_type(data_type); + const float shape_x = reshaped_weights_shape.x(); + reshaped_weights_shape.set(0, reshaped_weights_shape.y() * transpose_width); + reshaped_weights_shape.set(1, static_cast<unsigned int>(std::ceil(shape_x / transpose_width))); + } + } + + // Create tensors + TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, fixed_point_position); + TensorType weights = create_tensor<TensorType>(reshaped_weights_shape, data_type, 1, fixed_point_position); + TensorType bias = create_tensor<TensorType>(bias_shape, data_type, 1, fixed_point_position); + TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, fixed_point_position); + + // Create and configure function. + FunctionType fc; + fc.configure(&src, &weights, &bias, &dst, transpose_weights, !reshape_weights); + + 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); + + // Allocate tensors + src.allocator()->allocate(); + weights.allocator()->allocate(); + bias.allocator()->allocate(); + dst.allocator()->allocate(); + + 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); + + // Fill tensors + fill(AccessorType(src), 0); + fill(AccessorType(bias), 2); + + if(!reshape_weights || !transpose_weights) + { + TensorShape tmp_shape(weights_shape); + RawTensor tmp(tmp_shape, data_type, 1, fixed_point_position); + + // Fill with original shape + fill(tmp, 1); + + // Transpose elementwise + tmp = transpose(tmp); + + // Reshape weights for batched runs + if(!reshape_weights && output_shape.y() > 1 && run_interleave) + { + // Transpose with interleave + const int interleave_size = 16 / tmp.element_size(); + tmp = transpose(tmp, interleave_size); + } + + AccessorType weights_accessor(weights); + + for(int i = 0; i < tmp.num_elements(); ++i) + { + Coordinates coord = index2coord(tmp.shape(), i); + std::copy_n(static_cast<const RawTensor::value_type *>(tmp(coord)), + tmp.element_size(), + static_cast<RawTensor::value_type *>(weights_accessor(coord))); + } + } + else + { + fill(AccessorType(weights), 1); + } + + // Compute NEFullyConnectedLayer function + fc.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, bool transpose_weights, + bool reshape_weights, DataType data_type, int fixed_point_position = 0) + { + // Create reference + SimpleTensor<T> src{ input_shape, data_type, 1, fixed_point_position }; + SimpleTensor<T> weights{ weights_shape, data_type, 1, fixed_point_position }; + SimpleTensor<T> bias{ bias_shape, data_type, 1, fixed_point_position }; + + // Fill reference + fill(src, 0); + fill(weights, 1); + fill(bias, 2); + + return reference::fully_connected_layer<T>(src, weights, bias, output_shape); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + int _fractional_bits{}; + DataType _data_type{}; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool run_interleave> +class FullyConnectedLayerValidationFixture : public FullyConnectedLayerValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T, run_interleave> +{ +public: + template <typename...> + void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, bool transpose_weights, bool reshape_weights, DataType data_type) + { + FullyConnectedLayerValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T, run_interleave>::setup(input_shape, weights_shape, bias_shape, output_shape, transpose_weights, + reshape_weights, data_type, + 0); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/GEMMFixture.h b/tests/validation/fixtures/GEMMFixture.h new file mode 100644 index 0000000000..923a29c7d0 --- /dev/null +++ b/tests/validation/fixtures/GEMMFixture.h @@ -0,0 +1,152 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_GEMM_FIXTURE +#define ARM_COMPUTE_TEST_GEMM_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/GEMM.h" +#include "tests/validation/Helpers.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class GEMMValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape_a, TensorShape shape_b, TensorShape shape_c, TensorShape output_shape, float alpha, float beta, DataType data_type, int fractional_bits) + { + _fractional_bits = fractional_bits; + _data_type = data_type; + + _target = compute_target(shape_a, shape_b, shape_c, output_shape, alpha, beta, data_type, fractional_bits); + _reference = compute_reference(shape_a, shape_b, shape_c, output_shape, alpha, beta, data_type, fractional_bits); + } + +protected: + template <typename U> + void fill(U &&tensor, int i) + { + switch(tensor.data_type()) + { + case DataType::F16: + case DataType::F32: + { + std::uniform_real_distribution<> distribution(-1.0f, 1.0f); + library->fill(tensor, distribution, i); + break; + } + default: + library->fill_tensor_uniform(tensor, i); + } + } + + TensorType compute_target(const TensorShape &shape_a, const TensorShape &shape_b, const TensorShape &shape_c, const TensorShape &output_shape, float alpha, float beta, + DataType data_type, int fixed_point_position) + { + // Create tensors + TensorType a = create_tensor<TensorType>(shape_a, data_type, 1, fixed_point_position); + TensorType b = create_tensor<TensorType>(shape_b, data_type, 1, fixed_point_position); + TensorType c = create_tensor<TensorType>(shape_c, data_type, 1, fixed_point_position); + TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, fixed_point_position); + + // Create and configure function + FunctionType gemm; + gemm.configure(&a, &b, &c, &dst, alpha, beta); + + ARM_COMPUTE_EXPECT(a.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(b.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(c.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + a.allocator()->allocate(); + b.allocator()->allocate(); + c.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!a.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!b.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!c.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(a), 0); + fill(AccessorType(b), 1); + fill(AccessorType(c), 2); + + // Compute GEMM function + gemm.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape_a, const TensorShape &shape_b, const TensorShape &shape_c, const TensorShape &output_shape, float alpha, float beta, + DataType data_type, int fixed_point_position) + { + // Create reference + SimpleTensor<T> a{ shape_a, data_type, 1, fixed_point_position }; + SimpleTensor<T> b{ shape_b, data_type, 1, fixed_point_position }; + SimpleTensor<T> c{ shape_c, data_type, 1, fixed_point_position }; + + // Fill reference + fill(a, 0); + fill(b, 1); + fill(c, 2); + + return reference::gemm<T>(a, b, c, alpha, beta); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + int _fractional_bits{}; + DataType _data_type{}; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class GEMMValidationFixture : public GEMMValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape shape_a, TensorShape shape_b, TensorShape shape_c, TensorShape output_shape, float alpha, float beta, DataType data_type) + { + GEMMValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(shape_a, shape_b, shape_c, output_shape, alpha, beta, data_type, 0); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_GEMM_FIXTURE */ diff --git a/tests/validation/fixtures/L2NormalizeFixture.h b/tests/validation/fixtures/L2NormalizeFixture.h new file mode 100644 index 0000000000..e6113937f1 --- /dev/null +++ b/tests/validation/fixtures/L2NormalizeFixture.h @@ -0,0 +1,107 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_L2NORMALIZE_FIXTURE +#define ARM_COMPUTE_TEST_L2NORMALIZE_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/L2Normalize.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class L2NormalizeValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type, unsigned int axis, float epsilon) + { + _target = compute_target(shape, data_type, axis, epsilon); + _reference = compute_reference(shape, data_type, axis, epsilon); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type, unsigned int axis, float epsilon) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(shape, data_type); + + // Create and configure function + FunctionType l2_norm_func; + l2_norm_func.configure(&src, &dst, axis, epsilon); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + l2_norm_func.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type, unsigned int axis, float epsilon) + { + // Create reference + SimpleTensor<T> src{ shape, data_type }; + + // Fill reference + fill(src); + + return reference::l2_normalize<T>(src, axis, epsilon); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_L2NORMALIZE_FIXTURE */ diff --git a/tests/validation/fixtures/MeanStdDevFixture.h b/tests/validation/fixtures/MeanStdDevFixture.h new file mode 100644 index 0000000000..37f538b216 --- /dev/null +++ b/tests/validation/fixtures/MeanStdDevFixture.h @@ -0,0 +1,102 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_MEAN_STD_DEV_FIXTURE +#define ARM_COMPUTE_TEST_MEAN_STD_DEV_FIXTURE + +#include "tests/Globals.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/MeanStdDev.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class MeanStdDevValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + _target = compute_target(shape, data_type); + _reference = compute_reference(shape, data_type); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + std::pair<float, float> compute_target(const TensorShape &shape, DataType data_type) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type); + + // Create output variables + float mean = 0.0f; + float std_dev = 0.0f; + + // Create and configure function + FunctionType mean_std_dev; + mean_std_dev.configure(&src, &mean, &std_dev); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + mean_std_dev.run(); + + return std::make_pair(mean, std_dev); + } + + std::pair<float, float> compute_reference(const TensorShape &shape, DataType data_type) + { + // Create reference + SimpleTensor<T> src{ shape, data_type }; + + // Fill reference + fill(src); + + // Compute reference + return reference::mean_and_standard_deviation<T>(src); + } + + std::pair<float, float> _target{}; + std::pair<float, float> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_MEAN_STD_DEV_FIXTURE */ diff --git a/tests/validation/fixtures/NormalizationLayerFixture.h b/tests/validation/fixtures/NormalizationLayerFixture.h new file mode 100644 index 0000000000..696d14fbbb --- /dev/null +++ b/tests/validation/fixtures/NormalizationLayerFixture.h @@ -0,0 +1,133 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_NORMALIZATION_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_NORMALIZATION_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/NormalizationLayer.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class NormalizationValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, NormType norm_type, int norm_size, float beta, DataType data_type, int fractional_bits) + { + _fractional_bits = fractional_bits; + NormalizationLayerInfo info(norm_type, norm_size, 5, beta); + + _target = compute_target(shape, info, data_type, fractional_bits); + _reference = compute_reference(shape, info, data_type, fractional_bits); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + if(_fractional_bits == 0) + { + library->fill_tensor_uniform(tensor, 0); + } + else + { + const int one_fixed = 1 << _fractional_bits; + std::uniform_int_distribution<> distribution(-one_fixed, one_fixed); + library->fill(tensor, distribution, 0); + } + } + + TensorType compute_target(const TensorShape &shape, NormalizationLayerInfo info, DataType data_type, int fixed_point_position = 0) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position); + TensorType dst = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position); + + // Create and configure function + FunctionType norm_layer; + norm_layer.configure(&src, &dst, info); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + norm_layer.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, NormalizationLayerInfo info, DataType data_type, int fixed_point_position = 0) + { + // Create reference + SimpleTensor<T> src{ shape, data_type, 1, fixed_point_position }; + + // Fill reference + fill(src); + + return reference::normalization_layer<T>(src, info); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + int _fractional_bits{}; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class NormalizationValidationFixture : public NormalizationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape shape, NormType norm_type, int norm_size, float beta, DataType data_type) + { + NormalizationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, norm_type, norm_size, beta, data_type, 0); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_NORMALIZATION_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/PoolingLayerFixture.h b/tests/validation/fixtures/PoolingLayerFixture.h new file mode 100644 index 0000000000..5ce4aa6755 --- /dev/null +++ b/tests/validation/fixtures/PoolingLayerFixture.h @@ -0,0 +1,134 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_POOLING_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_POOLING_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/PoolingLayer.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class PoolingLayerValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, PoolingType pool_type, int pool_size, PadStrideInfo pad_stride_info, DataType data_type, int fractional_bits) + { + _fractional_bits = fractional_bits; + PoolingLayerInfo info(pool_type, pool_size, pad_stride_info); + + _target = compute_target(shape, info, data_type, fractional_bits); + _reference = compute_reference(shape, info, data_type, fractional_bits); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + if(_fractional_bits == 0) + { + std::uniform_real_distribution<> distribution(-1.f, 1.f); + library->fill(tensor, distribution, 0); + } + else + { + const int one_fixed = 1 << _fractional_bits; + std::uniform_int_distribution<> distribution(-one_fixed, one_fixed); + library->fill(tensor, distribution, 0); + } + } + + TensorType compute_target(const TensorShape &shape, PoolingLayerInfo info, DataType data_type, int fixed_point_position = 0) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position); + TensorType dst; + + // Create and configure function + FunctionType pool_layer; + pool_layer.configure(&src, &dst, info); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + pool_layer.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, PoolingLayerInfo info, DataType data_type, int fixed_point_position = 0) + { + // Create reference + SimpleTensor<T> src{ shape, data_type, 1, fixed_point_position }; + + // Fill reference + fill(src); + + return reference::pooling_layer<T>(src, info); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + int _fractional_bits{}; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class PoolingLayerValidationFixture : public PoolingLayerValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape shape, PoolingType pool_type, int pool_size, PadStrideInfo pad_stride_info, DataType data_type) + { + PoolingLayerValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, pool_type, pool_size, pad_stride_info, data_type, 0); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_POOLING_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/QuantizationLayerFixture.h b/tests/validation/fixtures/QuantizationLayerFixture.h new file mode 100644 index 0000000000..83ee0495f3 --- /dev/null +++ b/tests/validation/fixtures/QuantizationLayerFixture.h @@ -0,0 +1,120 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_QUANTIZATION_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_QUANTIZATION_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/QuantizationLayer.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class QuantizationValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + _target = compute_target(shape, data_type); + _reference = compute_reference(shape, data_type); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(shape, DataType::U8); + + // Create and configure function + FunctionType quantization_layer; + quantization_layer.configure(&src, &dst); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + quantization_layer.run(); + + return dst; + } + + SimpleTensor<uint8_t> compute_reference(const TensorShape &shape, DataType data_type) + { + // Create reference + SimpleTensor<T> src{ shape, data_type }; + + // Fill reference + fill(src); + + return reference::quantization_layer<T>(src); + } + + TensorType _target{}; + SimpleTensor<uint8_t> _reference{}; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class QuantizationValidationFixture : public QuantizationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + QuantizationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, data_type); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_QUANTIZATION_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/ReductionOperationFixture.h b/tests/validation/fixtures/ReductionOperationFixture.h new file mode 100644 index 0000000000..7c871aed3b --- /dev/null +++ b/tests/validation/fixtures/ReductionOperationFixture.h @@ -0,0 +1,116 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_REDUCTION_OPERATION_FIXTURE +#define ARM_COMPUTE_TEST_REDUCTION_OPERATION_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/ReductionOperation.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class ReductionOperationValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type, unsigned int axis, ReductionOperation op) + { + const TensorShape output_shape = get_output_shape(shape, axis); + _target = compute_target(shape, output_shape, data_type, axis, op); + _reference = compute_reference(shape, output_shape, data_type, axis, op); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + TensorType compute_target(const TensorShape &src_shape, const TensorShape &dst_shape, DataType data_type, unsigned int axis, ReductionOperation op) + { + // Create tensors + TensorType src = create_tensor<TensorType>(src_shape, data_type); + TensorType dst = create_tensor<TensorType>(dst_shape, data_type); + + // Create and configure function + FunctionType reduction_func; + reduction_func.configure(&src, &dst, axis, op); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + reduction_func.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &src_shape, const TensorShape &dst_shape, DataType data_type, unsigned int axis, ReductionOperation op) + { + // Create reference + SimpleTensor<T> src{ src_shape, data_type }; + + // Fill reference + fill(src); + + return reference::reduction_operation<T>(src, dst_shape, axis, op); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + +private: + TensorShape get_output_shape(TensorShape shape, unsigned int axis) + { + TensorShape output_shape(shape); + output_shape.set(axis, 1); + return output_shape; + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_REDUCTION_OPERATION_FIXTURE */ diff --git a/tests/validation/fixtures/ScaleFixture.h b/tests/validation/fixtures/ScaleFixture.h new file mode 100644 index 0000000000..53bb0f2124 --- /dev/null +++ b/tests/validation/fixtures/ScaleFixture.h @@ -0,0 +1,127 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_SCALE_FIXTURE +#define ARM_COMPUTE_TEST_SCALE_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/Scale.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class ScaleValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type, InterpolationPolicy policy, BorderMode border_mode) + { + _shape = shape; + _policy = policy; + _border_mode = border_mode; + _data_type = data_type; + + std::mt19937 generator(library->seed()); + std::uniform_real_distribution<float> distribution_float(0.25, 4); + const float scale_x = distribution_float(generator); + const float scale_y = distribution_float(generator); + std::uniform_int_distribution<uint8_t> distribution_u8(0, 255); + uint8_t constant_border_value = distribution_u8(generator); + + _target = compute_target(shape, scale_x, scale_y, policy, border_mode, constant_border_value); + _reference = compute_reference(shape, scale_x, scale_y, policy, border_mode, constant_border_value); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + TensorType compute_target(const TensorShape &shape, const float scale_x, const float scale_y, + InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, _data_type); + TensorShape shape_scaled(shape); + shape_scaled.set(0, shape[0] * scale_x); + shape_scaled.set(1, shape[1] * scale_y); + TensorType dst = create_tensor<TensorType>(shape_scaled, _data_type); + + // Create and configure function + FunctionType scale; + + scale.configure(&src, &dst, policy, border_mode, constant_border_value); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + scale.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, const float scale_x, const float scale_y, + InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value) + { + // Create reference + SimpleTensor<T> src{ shape, _data_type }; + + // Fill reference + fill(src); + + return reference::scale<T>(src, scale_x, scale_y, policy, border_mode, constant_border_value); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + TensorShape _shape{}; + InterpolationPolicy _policy{}; + BorderMode _border_mode{}; + DataType _data_type{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_SCALE_FIXTURE */
\ No newline at end of file diff --git a/tests/validation/fixtures/SoftmaxLayerFixture.h b/tests/validation/fixtures/SoftmaxLayerFixture.h new file mode 100644 index 0000000000..9c8f044e81 --- /dev/null +++ b/tests/validation/fixtures/SoftmaxLayerFixture.h @@ -0,0 +1,133 @@ +/* + * 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. + */ +#ifndef ARM_COMPUTE_TEST_SOFTMAX_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_SOFTMAX_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/CPP/SoftmaxLayer.h" + +#include <random> + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class SoftmaxValidationFixedPointFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type, int fractional_bits) + { + _fractional_bits = fractional_bits; + + _target = compute_target(shape, data_type, fractional_bits); + _reference = compute_reference(shape, data_type, fractional_bits); + } + +protected: + template <typename U> + void fill(U &&tensor) + { + if(_fractional_bits == 0) + { + std::uniform_real_distribution<> distribution(-1000.f, 1000.f); + library->fill(tensor, distribution, 0); + } + else + { + const int one_fixed = 1 << _fractional_bits; + std::uniform_int_distribution<> distribution(-one_fixed, one_fixed); + library->fill(tensor, distribution, 0); + } + } + + TensorType compute_target(const TensorShape &shape, DataType data_type, int fixed_point_position = 0) + { + // Create tensors + TensorType src = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position); + TensorType dst = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position); + + // Create and configure function + FunctionType smx_layer; + smx_layer.configure(&src, &dst); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + smx_layer.run(); + + return dst; + } + + SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type, int fixed_point_position = 0) + { + // Create reference + SimpleTensor<T> src{ shape, data_type, 1, fixed_point_position }; + + // Fill reference + fill(src); + + return reference::softmax_layer<T>(src); + } + + TensorType _target{}; + SimpleTensor<T> _reference{}; + int _fractional_bits{}; +}; + +template <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class SoftmaxValidationFixture : public SoftmaxValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T> +{ +public: + template <typename...> + void setup(TensorShape shape, DataType data_type) + { + SoftmaxValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, data_type, 0); + } +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_SOFTMAX_LAYER_FIXTURE */ diff --git a/tests/validation/half.h b/tests/validation/half.h index d8aa341068..0ca620cf57 100644 --- a/tests/validation/half.h +++ b/tests/validation/half.h @@ -34,4 +34,5 @@ #define HALF_ROUND_TIES_TO_EVEN 1 #include "half/half.hpp" + #endif /* __ARM_COMPUTE_TEST_HALF_H__ */ diff --git a/tests/validation/main.cpp b/tests/validation/main.cpp deleted file mode 100644 index a6c02ed4dd..0000000000 --- a/tests/validation/main.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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. - */ -#define BOOST_TEST_ALTERNATIVE_INIT_API - -#include "AssetsLibrary.h" -#include "Globals.h" -#include "Utils.h" -#include "ValidationProgramOptions.h" -#include "ValidationUserConfiguration.h" -#include "support/ToolchainSupport.h" - -#include "arm_compute/runtime/Scheduler.h" - -#include "boost_wrapper.h" - -#include <iostream> -#include <memory> -#include <random> - -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace arm_compute -{ -namespace test -{ -ValidationUserConfiguration user_config; -std::unique_ptr<AssetsLibrary> library; -} // namespace test -} // namespace arm_compute - -struct GlobalFixture -{ - GlobalFixture() - { - library = arm_compute::support::cpp14::make_unique<AssetsLibrary>(user_config.path.get(), user_config.seed); - std::cout << "Seed: " << library->seed() << "\n"; - } -}; - -BOOST_GLOBAL_FIXTURE(GlobalFixture); - -bool init_unit_test() -{ - boost::unit_test::framework::master_test_suite().p_name.value = "Compute Library Validation Tests"; - - ValidationProgramOptions options; - - int &argc = boost::unit_test::framework::master_test_suite().argc; - char **argv = boost::unit_test::framework::master_test_suite().argv; - - try - { - options.parse_commandline(argc, argv); - - if(options.wants_help()) - { - std::cout << "Usage: " << argv[0] << " [options] PATH\n"; - std::cout << options.get_help() << "\n"; - return false; - } - - user_config = ValidationUserConfiguration(options); - } - catch(const boost::program_options::required_option &err) - { - std::cerr << "Error: " << err.what() << "\n"; - std::cout << "\nUsage: " << argv[0] << " [options] PATH\n"; - std::cout << options.get_help() << "\n"; - return false; - } - - std::cout << "Using " << user_config.threads << " CPU " << (user_config.threads == 1 ? "thread" : "threads") << "\n"; - arm_compute::Scheduler::get().set_num_threads(user_config.threads); - return true; -} diff --git a/tests/validation/system_tests/CL/AlexNet.cpp b/tests/validation/system_tests/CL/AlexNet.cpp deleted file mode 100644 index 2b1d31f65f..0000000000 --- a/tests/validation/system_tests/CL/AlexNet.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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. - */ -#ifdef INTERNAL_ONLY //FIXME Delete this file before the release -/* - * 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 "CL/CLAccessor.h" -#include "validation/Validation.h" - -#include "arm_compute/runtime/CL/CLSubTensor.h" -#include "arm_compute/runtime/CL/functions/CLActivationLayer.h" -#include "arm_compute/runtime/CL/functions/CLConvolutionLayer.h" -#include "arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h" -#include "arm_compute/runtime/CL/functions/CLNormalizationLayer.h" -#include "arm_compute/runtime/CL/functions/CLPoolingLayer.h" -#include "arm_compute/runtime/CL/functions/CLSoftmaxLayer.h" - -#include "model_objects/AlexNet.h" - -#include <array> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -using CLAlexNetModel = model_objects::AlexNet<ICLTensor, - CLTensor, - CLSubTensor, - CLAccessor, - CLActivationLayer, - CLConvolutionLayer, - CLFullyConnectedLayer, - CLNormalizationLayer, - CLPoolingLayer, - CLSoftmaxLayer>; -std::vector<unsigned int> compute_alexnet(unsigned int batches, std::string input_file) -{ - std::vector<std::string> weight_files = { "cnn_data/alexnet_model/conv1_w.dat", - "cnn_data/alexnet_model/conv2_w.dat", - "cnn_data/alexnet_model/conv3_w.dat", - "cnn_data/alexnet_model/conv4_w.dat", - "cnn_data/alexnet_model/conv5_w.dat", - "cnn_data/alexnet_model/fc6_w.dat", - "cnn_data/alexnet_model/fc7_w.dat", - "cnn_data/alexnet_model/fc8_w.dat" - }; - - std::vector<std::string> bias_files = { "cnn_data/alexnet_model/conv1_b.dat", - "cnn_data/alexnet_model/conv2_b.dat", - "cnn_data/alexnet_model/conv3_b.dat", - "cnn_data/alexnet_model/conv4_b.dat", - "cnn_data/alexnet_model/conv5_b.dat", - "cnn_data/alexnet_model/fc6_b.dat", - "cnn_data/alexnet_model/fc7_b.dat", - "cnn_data/alexnet_model/fc8_b.dat" - }; - CLAlexNetModel network{}; - network.init_weights(batches); - network.build(); - network.allocate(); - network.fill(weight_files, bias_files); - network.feed(std::move(input_file)); - network.run(); - - return network.get_classifications(); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(SYSTEM_TESTS) -BOOST_AUTO_TEST_SUITE(CL) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_AUTO_TEST_CASE(AlexNet) -{ - // Compute alexnet - std::vector<unsigned int> classified_labels = compute_alexnet(1, "cnn_data/imagenet_data/shark.dat"); - - // Expected labels - std::vector<unsigned int> expected_labels = { 2 }; - - // Validate labels - validate(classified_labels, expected_labels); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ -#endif /* INTERNAL_ONLY */ diff --git a/tests/validation/system_tests/CL/LeNet5.cpp b/tests/validation/system_tests/CL/LeNet5.cpp deleted file mode 100644 index 4b3d969a1d..0000000000 --- a/tests/validation/system_tests/CL/LeNet5.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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. - */ -#ifdef INTERNAL_ONLY //FIXME Delete this file before the release -/* - * 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 "CL/CLAccessor.h" -#include "validation/Validation.h" - -#include "arm_compute/runtime/CL/functions/CLActivationLayer.h" -#include "arm_compute/runtime/CL/functions/CLConvolutionLayer.h" -#include "arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h" -#include "arm_compute/runtime/CL/functions/CLPoolingLayer.h" -#include "arm_compute/runtime/CL/functions/CLSoftmaxLayer.h" - -#include "model_objects/LeNet5.h" - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -using CLLeNet5Model = model_objects::LeNet5<CLTensor, - CLAccessor, - CLActivationLayer, - CLConvolutionLayer, - CLFullyConnectedLayer, - CLPoolingLayer, - CLSoftmaxLayer>; -std::vector<unsigned int> compute_lenet5(unsigned int batches, std::string input_file) -{ - std::vector<std::string> weight_files = { "cnn_data/lenet_model/conv1_w.dat", - "cnn_data/lenet_model/conv2_w.dat", - "cnn_data/lenet_model/ip1_w.dat", - "cnn_data/lenet_model/ip2_w.dat" - }; - - std::vector<std::string> bias_files = { "cnn_data/lenet_model/conv1_b.dat", - "cnn_data/lenet_model/conv2_b.dat", - "cnn_data/lenet_model/ip1_b.dat", - "cnn_data/lenet_model/ip2_b.dat" - }; - CLLeNet5Model network{}; - network.build(batches); - network.fill(weight_files, bias_files); - network.feed(std::move(input_file)); - network.run(); - - return network.get_classifications(); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(SYSTEM_TESTS) -BOOST_AUTO_TEST_SUITE(CL) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_AUTO_TEST_CASE(LeNet5) -{ - // Compute alexnet - std::vector<unsigned int> classified_labels = compute_lenet5(10, "cnn_data/mnist_data/input100.dat"); - - // Expected labels - std::vector<unsigned int> expected_labels = { 7, 2, 1, 0, 4, 1, 4, 9, 5, 9 }; - - // Validate labels - validate(classified_labels, expected_labels); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ -#endif /* INTERNAL_ONLY */ diff --git a/tests/validation/system_tests/NEON/AlexNet.cpp b/tests/validation/system_tests/NEON/AlexNet.cpp deleted file mode 100644 index 20a612fd64..0000000000 --- a/tests/validation/system_tests/NEON/AlexNet.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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. - */ -#ifdef INTERNAL_ONLY //FIXME Delete this file before the release -/* - * 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 "NEON/Accessor.h" -#include "validation/Validation.h" - -#include "arm_compute/runtime/NEON/functions/NEActivationLayer.h" -#include "arm_compute/runtime/NEON/functions/NEConvolutionLayer.h" -#include "arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h" -#include "arm_compute/runtime/NEON/functions/NENormalizationLayer.h" -#include "arm_compute/runtime/NEON/functions/NEPoolingLayer.h" -#include "arm_compute/runtime/NEON/functions/NESoftmaxLayer.h" -#include "arm_compute/runtime/SubTensor.h" - -#include "model_objects/AlexNet.h" - -#include <array> - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -using NEAlexNetModel = model_objects::AlexNet<ITensor, - Tensor, - SubTensor, - Accessor, - NEActivationLayer, - NEConvolutionLayer, - NEFullyConnectedLayer, - NENormalizationLayer, - NEPoolingLayer, - NESoftmaxLayer>; -std::vector<unsigned int> compute_alexnet(unsigned int batches, std::string input_file) -{ - std::vector<std::string> weight_files = { "cnn_data/alexnet_model/conv1_w.dat", - "cnn_data/alexnet_model/conv2_w.dat", - "cnn_data/alexnet_model/conv3_w.dat", - "cnn_data/alexnet_model/conv4_w.dat", - "cnn_data/alexnet_model/conv5_w.dat", - "cnn_data/alexnet_model/fc6_w.dat", - "cnn_data/alexnet_model/fc7_w.dat", - "cnn_data/alexnet_model/fc8_w.dat" - }; - - std::vector<std::string> bias_files = { "cnn_data/alexnet_model/conv1_b.dat", - "cnn_data/alexnet_model/conv2_b.dat", - "cnn_data/alexnet_model/conv3_b.dat", - "cnn_data/alexnet_model/conv4_b.dat", - "cnn_data/alexnet_model/conv5_b.dat", - "cnn_data/alexnet_model/fc6_b.dat", - "cnn_data/alexnet_model/fc7_b.dat", - "cnn_data/alexnet_model/fc8_b.dat" - }; - NEAlexNetModel network{}; - - network.init_weights(batches); - network.build(); - network.allocate(); - network.fill(weight_files, bias_files); - network.feed(std::move(input_file)); - network.run(); - - return network.get_classifications(); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(SYSTEM_TESTS) -BOOST_AUTO_TEST_SUITE(NEON) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_AUTO_TEST_CASE(AlexNet) -{ - // Compute alexnet - std::vector<unsigned int> classified_labels = compute_alexnet(1, "cnn_data/imagenet_data/shark.dat"); - - // Expected labels - std::vector<unsigned int> expected_labels = { 2 }; - - // Validate labels - validate(classified_labels, expected_labels); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ -#endif /* INTERNAL_ONLY */ diff --git a/tests/validation/system_tests/NEON/LeNet5.cpp b/tests/validation/system_tests/NEON/LeNet5.cpp deleted file mode 100644 index c745613959..0000000000 --- a/tests/validation/system_tests/NEON/LeNet5.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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. - */ -#ifdef INTERNAL_ONLY //FIXME Delete this file before the release -/* - * 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 "NEON/Accessor.h" -#include "validation/Validation.h" - -#include "arm_compute/runtime/NEON/functions/NEActivationLayer.h" -#include "arm_compute/runtime/NEON/functions/NEConvolutionLayer.h" -#include "arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h" -#include "arm_compute/runtime/NEON/functions/NEPoolingLayer.h" -#include "arm_compute/runtime/NEON/functions/NESoftmaxLayer.h" - -#include "model_objects/LeNet5.h" - -using namespace arm_compute; -using namespace arm_compute::test; -using namespace arm_compute::test::validation; - -namespace -{ -using NELeNet5Model = model_objects::LeNet5<Tensor, - Accessor, - NEActivationLayer, - NEConvolutionLayer, - NEFullyConnectedLayer, - NEPoolingLayer, - NESoftmaxLayer>; -std::vector<unsigned int> compute_lenet5(unsigned int batches, std::string input_file) -{ - std::vector<std::string> weight_files = { "cnn_data/lenet_model/conv1_w.dat", - "cnn_data/lenet_model/conv2_w.dat", - "cnn_data/lenet_model/ip1_w.dat", - "cnn_data/lenet_model/ip2_w.dat" - }; - - std::vector<std::string> bias_files = { "cnn_data/lenet_model/conv1_b.dat", - "cnn_data/lenet_model/conv2_b.dat", - "cnn_data/lenet_model/ip1_b.dat", - "cnn_data/lenet_model/ip2_b.dat" - }; - NELeNet5Model network{}; - network.build(batches); - network.fill(weight_files, bias_files); - network.feed(std::move(input_file)); - network.run(); - - return network.get_classifications(); -} -} // namespace - -#ifndef DOXYGEN_SKIP_THIS -BOOST_AUTO_TEST_SUITE(SYSTEM_TESTS) -BOOST_AUTO_TEST_SUITE(NEON) - -BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit")) -BOOST_AUTO_TEST_CASE(LeNet5) -{ - // Compute alexnet - std::vector<unsigned int> classified_labels = compute_lenet5(10, "cnn_data/mnist_data/input100.dat"); - - // Expected labels - std::vector<unsigned int> expected_labels = { 7, 2, 1, 0, 4, 1, 4, 9, 5, 9 }; - - // Validate labels - validate(classified_labels, expected_labels); -} - -BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE_END() -#endif /* DOXYGEN_SKIP_THIS */ -#endif /* INTERNAL_ONLY */ |