From eb312ef6c20e8548c43eb9d4a3edf7265bc6777b Mon Sep 17 00:00:00 2001 From: Usama Arif Date: Mon, 13 May 2019 17:45:54 +0100 Subject: COMPMID-2267: Implement NEG for CL Change-Id: I5019103987c92df5080809201feb9b646fae8cc5 Signed-off-by: Usama Arif Reviewed-on: https://review.mlplatform.org/c/1130 Comments-Addressed: Arm Jenkins Reviewed-by: Gian Marco Iodice Tested-by: Arm Jenkins --- .../runtime/CL/functions/CLElementWiseUnaryLayer.h | 22 +++++- src/core/CL/cl_kernels/elementwise_unary.cl | 53 ++----------- .../CL/kernels/CLElementWiseUnaryLayerKernel.cpp | 5 +- .../CL/functions/CLElementWiseUnaryLayer.cpp | 14 +++- tests/validation/CL/NegLayer.cpp | 90 ++++++++++++++++++++++ utils/TypePrinter.h | 3 + 6 files changed, 138 insertions(+), 49 deletions(-) create mode 100644 tests/validation/CL/NegLayer.cpp diff --git a/arm_compute/runtime/CL/functions/CLElementWiseUnaryLayer.h b/arm_compute/runtime/CL/functions/CLElementWiseUnaryLayer.h index 37061a647c..a2012ab054 100644 --- a/arm_compute/runtime/CL/functions/CLElementWiseUnaryLayer.h +++ b/arm_compute/runtime/CL/functions/CLElementWiseUnaryLayer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 ARM Limited. + * Copyright (c) 2018-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -69,5 +69,25 @@ public: */ static Status validate(const ITensorInfo *input, const ITensorInfo *output); }; + +/** Basic function to negate an input tensor. */ +class CLNegLayer : public ICLSimpleFunction +{ +public: + /** Initialize the function + * + * @param[in] input Input tensor. Data types supported: F16/F32. + * @param[out] output Output tensor. Data types supported: same as @p input. + */ + void configure(const ICLTensor *input, ICLTensor *output); + /** Static function to check if given info will lead to a valid configuration of @ref CLNegLayer + * + * @param[in] input First tensor input info. Data types supported: F16/F32. + * @param[in] output Output tensor info. Data types supported: Same as @p input. + * + * @return a status + */ + static Status validate(const ITensorInfo *input, const ITensorInfo *output); +}; } // namespace arm_compute #endif /* __ARM_COMPUTE_CLELEMENTWISEUNARYLAYER_H__ */ diff --git a/src/core/CL/cl_kernels/elementwise_unary.cl b/src/core/CL/cl_kernels/elementwise_unary.cl index 92db569d97..2650654e4a 100644 --- a/src/core/CL/cl_kernels/elementwise_unary.cl +++ b/src/core/CL/cl_kernels/elementwise_unary.cl @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 ARM Limited. + * Copyright (c) 2018-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -26,51 +26,12 @@ #if defined(DATA_TYPE) && defined(OPERATION) -#if defined(VEC_SIZE) && defined(LAST_ACCESSED_X) -/** Calculate reverse square root - * - * @param[in] input Pointer to the first element. - * - * @return reverse square root - */ -inline VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE) inverse_sqrt(const VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE) input) -{ - return rsqrt(input); -} - -/** Calculate exponential - * - * @param[in] input Pointer to the first element. - * - * @return exponential - */ -inline VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE) exponential(const VEC_DATA_TYPE(DATA_TYPE, VEC_SIZE) input) -{ - return exp(input); -} -#else // !defined(VEC_SIZE) || !defined(LAST_ACCESSED_X) -/** Calculate reverse square root - * - * @param[in] input Single element. - * - * @return reverse square root - */ -inline DATA_TYPE inverse_sqrt(const DATA_TYPE input) -{ - return rsqrt(input); -} - -/** Calculate exponential - * - * @param[in] input Single element. - * - * @return exponential - */ -inline DATA_TYPE exponential(const DATA_TYPE input) -{ - return exp(input); -} -#endif // defined(VEC_SIZE) && defined(LAST_ACCESSED_X) +// Calculate Exponential +#define exponential(input) exp(input) +// Calculate reverse square root +#define inverse_sqrt(input) rsqrt(input) +// Calculate negative +#define neg(input) (-input) /** Applies element wise unary operator in a tensor. * diff --git a/src/core/CL/kernels/CLElementWiseUnaryLayerKernel.cpp b/src/core/CL/kernels/CLElementWiseUnaryLayerKernel.cpp index be3c7e25da..e804ef1853 100644 --- a/src/core/CL/kernels/CLElementWiseUnaryLayerKernel.cpp +++ b/src/core/CL/kernels/CLElementWiseUnaryLayerKernel.cpp @@ -84,6 +84,9 @@ void CLElementWiseUnaryLayerKernel::configure(const ICLTensor *input, ICLTensor case ElementWiseUnary::EXP: build_opts.add_option("-DOPERATION=exponential"); break; + case ElementWiseUnary::NEG: + build_opts.add_option("-DOPERATION=neg"); + break; default: ARM_COMPUTE_ERROR("Not implemented"); } @@ -116,4 +119,4 @@ void CLElementWiseUnaryLayerKernel::run(const Window &window, cl::CommandQueue & enqueue(queue, *this, collapsed); } while(window.slide_window_slice_1D(collapsed)); -} \ No newline at end of file +} diff --git a/src/runtime/CL/functions/CLElementWiseUnaryLayer.cpp b/src/runtime/CL/functions/CLElementWiseUnaryLayer.cpp index b7e9a68680..67ffec8991 100644 --- a/src/runtime/CL/functions/CLElementWiseUnaryLayer.cpp +++ b/src/runtime/CL/functions/CLElementWiseUnaryLayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 ARM Limited. + * Copyright (c) 2018-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -51,4 +51,16 @@ Status CLExpLayer::validate(const ITensorInfo *input, const ITensorInfo *output) { return CLElementWiseUnaryLayerKernel::validate(input, output, ElementWiseUnary::EXP); } + +void CLNegLayer::configure(const ICLTensor *input, ICLTensor *output) +{ + auto k = arm_compute::support::cpp14::make_unique(); + k->configure(input, output, ElementWiseUnary::NEG); + _kernel = std::move(k); +} +Status CLNegLayer::validate(const ITensorInfo *input, const ITensorInfo *output) +{ + return CLElementWiseUnaryLayerKernel::validate(input, output, ElementWiseUnary::NEG); +} + } // namespace arm_compute diff --git a/tests/validation/CL/NegLayer.cpp b/tests/validation/CL/NegLayer.cpp new file mode 100644 index 0000000000..3dcb0ba727 --- /dev/null +++ b/tests/validation/CL/NegLayer.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019 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/CLElementWiseUnaryLayer.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/ElementWiseUnaryFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +RelativeTolerance tolerance_fp32(0.000001f); +RelativeTolerance tolerance_fp16(0.001f); +} // namespace +TEST_SUITE(CL) +TEST_SUITE(NegLayer) +template +using CLNegLayerFixture = NegValidationFixture; + +TEST_SUITE(Float) +TEST_SUITE(FP16) +FIXTURE_DATA_TEST_CASE(RunSmall, CLNegLayerFixture, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fp16); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLNegLayerFixture, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::F16))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fp16); +} + +TEST_SUITE_END() // FP16 +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, CLNegLayerFixture, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fp32); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CLNegLayerFixture, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), framework::dataset::make("DataType", + DataType::F32))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_fp32); +} + +TEST_SUITE_END() // FP32 +TEST_SUITE_END() // Float + +TEST_SUITE_END() // NegLayer +TEST_SUITE_END() // CL +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/utils/TypePrinter.h b/utils/TypePrinter.h index b22e068c69..62edea344a 100644 --- a/utils/TypePrinter.h +++ b/utils/TypePrinter.h @@ -1516,6 +1516,9 @@ inline ::std::ostream &operator<<(::std::ostream &os, const ElementWiseUnary &op case ElementWiseUnary::EXP: os << "EXP"; break; + case ElementWiseUnary::NEG: + os << "NEG"; + break; default: ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); } -- cgit v1.2.1