aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUsama Arif <usama.arif@arm.com>2019-05-14 10:22:36 +0100
committerUsama Arif <usama.arif@arm.com>2019-05-15 17:09:25 +0000
commit52c54f61b97bcedab309bfa761e193939e12e739 (patch)
treee99186abb3c6a69ef26b17e8fb57817ee56efe53
parenteb312ef6c20e8548c43eb9d4a3edf7265bc6777b (diff)
downloadComputeLibrary-52c54f61b97bcedab309bfa761e193939e12e739.tar.gz
COMPMID-2270: Implement POW operator for CL
Change-Id: Id14ecdc62439d90eb247bb75990d6593637cb42e Signed-off-by: Usama Arif <usama.arif@arm.com> Reviewed-on: https://review.mlplatform.org/c/1129 Comments-Addressed: Arm Jenkins <bsgcomp@arm.com> Reviewed-by: Gian Marco Iodice <gianmarco.iodice@arm.com> Tested-by: Arm Jenkins <bsgcomp@arm.com>
-rw-r--r--arm_compute/runtime/CL/functions/CLElementwiseOperations.h28
-rw-r--r--src/core/CL/CLKernelLibrary.cpp1
-rw-r--r--src/core/CL/cl_kernels/elementwise_operation.cl3
-rw-r--r--src/core/CL/kernels/CLElementwiseOperationKernel.cpp19
-rw-r--r--src/runtime/CL/functions/CLElementwiseOperations.cpp16
-rw-r--r--tests/validation/CL/ElementwisePower.cpp129
-rw-r--r--utils/TypePrinter.h3
7 files changed, 188 insertions, 11 deletions
diff --git a/arm_compute/runtime/CL/functions/CLElementwiseOperations.h b/arm_compute/runtime/CL/functions/CLElementwiseOperations.h
index 1740bb0e4d..27215e81c1 100644
--- a/arm_compute/runtime/CL/functions/CLElementwiseOperations.h
+++ b/arm_compute/runtime/CL/functions/CLElementwiseOperations.h
@@ -202,5 +202,33 @@ public:
*/
static Status validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output);
};
+
+/** Basic function to run @ref CLArithmeticOperationKernel for power
+ *
+ * @note The tensor data type for the inputs must be F16/F32.
+ * @note The function performs an elementwise power of in1 to in2 (i.e., out[i] = in1[i] ^ in2[i])
+ */
+class CLElementwisePower : public ICLSimpleFunction
+{
+public:
+ /** Initialise the kernel's inputs, output and conversion policy.
+ *
+ * @param[in, out] input1 First tensor input. Data types supported: F16/F32.
+ * The input tensor is [in, out] because its TensorInfo might be modified inside the kernel in case of broadcasting of dimension 0.
+ * @param[in, out] input2 Second tensor input. Data types supported: F16/F32.
+ * The input tensor is [in, out] because its TensorInfo might be modified inside the kernel in case of broadcasting of dimension 0.
+ * @param[out] output Output tensor. Data types supported:F16/F32.
+ */
+ void configure(ICLTensor *input1, ICLTensor *input2, ICLTensor *output);
+ /** Static function to check if given info will lead to a valid configuration of @ref CLArithmeticOperationKernel for power
+ *
+ * @param[in] input1 First tensor input info. Data types supported: F16/F32.
+ * @param[in] input2 Second tensor input info. Data types supported: F16/F32.
+ * @param[in] output Output tensor info. Data types supported: F16/F32.
+ *
+ * @return a status
+ */
+ static Status validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output);
+};
} // namespace arm_compute
#endif /* __ARM_COMPUTE_CLELEMENTWISEOPERATIONS_H__ */
diff --git a/src/core/CL/CLKernelLibrary.cpp b/src/core/CL/CLKernelLibrary.cpp
index b2d7e23624..e102f44b88 100644
--- a/src/core/CL/CLKernelLibrary.cpp
+++ b/src/core/CL/CLKernelLibrary.cpp
@@ -252,6 +252,7 @@ const std::map<std::string, std::string> CLKernelLibrary::_kernel_program_map =
{ "elementwise_operation_MIN", "elementwise_operation.cl" },
{ "elementwise_operation_DIV", "elementwise_operation.cl" },
{ "elementwise_operation_SQUARED_DIFF", "elementwise_operation.cl" },
+ { "elementwise_operation_POWER", "elementwise_operation.cl" },
{ "elementwise_operation_ADD_quantized", "elementwise_operation_quantized.cl" },
{ "elementwise_operation_SUB_quantized", "elementwise_operation_quantized.cl" },
{ "elementwise_operation_MAX_quantized", "elementwise_operation_quantized.cl" },
diff --git a/src/core/CL/cl_kernels/elementwise_operation.cl b/src/core/CL/cl_kernels/elementwise_operation.cl
index 00d7ed3ba1..0b660e4012 100644
--- a/src/core/CL/cl_kernels/elementwise_operation.cl
+++ b/src/core/CL/cl_kernels/elementwise_operation.cl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -37,6 +37,7 @@
#define MIN(x, y) min(x, y)
#define SQUARED_DIFF(x, y) (x - y) * (x - y)
#define DIV(x, y) (x / y)
+#define POWER(x, y) pow(x, y)
#define OP_FUN_NAME_STR(op) elementwise_operation_##op
#define OP_FUN_NAME(op) OP_FUN_NAME_STR(op)
diff --git a/src/core/CL/kernels/CLElementwiseOperationKernel.cpp b/src/core/CL/kernels/CLElementwiseOperationKernel.cpp
index 63c9244961..ce0c51dac5 100644
--- a/src/core/CL/kernels/CLElementwiseOperationKernel.cpp
+++ b/src/core/CL/kernels/CLElementwiseOperationKernel.cpp
@@ -42,6 +42,7 @@ std::map<ArithmeticOperation, std::string> supported_arithmetic_ops =
{ ArithmeticOperation::SQUARED_DIFF, "SQUARED_DIFF" },
{ ArithmeticOperation::MIN, "MIN" },
{ ArithmeticOperation::MAX, "MAX" },
+ { ArithmeticOperation::POWER, "POWER" },
};
std::map<ArithmeticOperation, std::string> supported_sat_arithmetic_ops =
@@ -64,7 +65,7 @@ std::string generate_id_for_tuning_common(const std::string &kernel_name, const
return config_id;
}
-Status validate_arguments_with_division_rules(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
+Status validate_arguments_with_float_only_supported_rules(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
{
ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(&input1, &input2, &output);
ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&input1);
@@ -344,10 +345,10 @@ void CLArithmeticOperationKernel::configure(ArithmeticOperation op, const ICLTen
Status CLArithmeticOperationKernel::validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
{
ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
- if(op == ArithmeticOperation::DIV)
+ if(op == ArithmeticOperation::DIV || op == ArithmeticOperation::POWER)
{
- // Division doesn't support integer arithmetic
- ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments_with_division_rules(*input1, *input2, *output));
+ // Division and Power operators don't support integer arithmetic
+ ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments_with_float_only_supported_rules(*input1, *input2, *output));
ARM_COMPUTE_RETURN_ON_ERROR(validate_and_configure_window_for_division(*input1->clone(), *input2->clone(), *output->clone()).first);
}
else
@@ -360,9 +361,9 @@ Status CLArithmeticOperationKernel::validate(ArithmeticOperation op, const ITens
}
std::pair<Status, Window> CLArithmeticOperationKernel::validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output)
{
- if(_op == ArithmeticOperation::DIV)
+ if(_op == ArithmeticOperation::DIV || _op == ArithmeticOperation::POWER)
{
- // Division doesn't support integer arithmetic
+ // Division and Power operators don't support integer arithmetic
return validate_and_configure_window_for_division(input1, input2, output);
}
else
@@ -372,10 +373,10 @@ std::pair<Status, Window> CLArithmeticOperationKernel::validate_and_configure_wi
}
Status CLArithmeticOperationKernel::validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output)
{
- if(_op == ArithmeticOperation::DIV)
+ if(_op == ArithmeticOperation::DIV || _op == ArithmeticOperation::POWER)
{
- // Division doesn't support integer arithmetic
- return validate_arguments_with_division_rules(input1, input2, output);
+ // Division and Power operators don't support integer arithmetic
+ return validate_arguments_with_float_only_supported_rules(input1, input2, output);
}
else
{
diff --git a/src/runtime/CL/functions/CLElementwiseOperations.cpp b/src/runtime/CL/functions/CLElementwiseOperations.cpp
index 28f4b13f22..15de56d24a 100644
--- a/src/runtime/CL/functions/CLElementwiseOperations.cpp
+++ b/src/runtime/CL/functions/CLElementwiseOperations.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -124,4 +124,18 @@ Status CLElementwiseSquaredDiff::validate(const ITensorInfo *input1, const ITens
{
return CLArithmeticOperationKernel::validate(ArithmeticOperation::SQUARED_DIFF, input1, input2, output);
}
+
+void CLElementwisePower::configure(ICLTensor *input1, ICLTensor *input2, ICLTensor *output)
+{
+ auto k = arm_compute::support::cpp14::make_unique<CLArithmeticOperationKernel>();
+ k->configure(ArithmeticOperation::POWER, input1, input2, output);
+ _kernel = std::move(k);
+ configure_border_handler(_border_handler, _kernel->border_size(), input1, input2, output);
+}
+
+Status CLElementwisePower::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
+{
+ return CLArithmeticOperationKernel::validate(ArithmeticOperation::POWER, input1, input2, output);
+}
+
} // namespace arm_compute
diff --git a/tests/validation/CL/ElementwisePower.cpp b/tests/validation/CL/ElementwisePower.cpp
new file mode 100644
index 0000000000..af36e1768b
--- /dev/null
+++ b/tests/validation/CL/ElementwisePower.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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/CLTensor.h"
+#include "arm_compute/runtime/CL/CLTensorAllocator.h"
+#include "arm_compute/runtime/CL/functions/CLElementwiseOperations.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/ElementwiseOperationsFixture.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace
+{
+RelativeTolerance<float> tolerance_fp32(0.000001f);
+RelativeTolerance<float> tolerance_fp16(0.001f);
+
+constexpr unsigned int num_elems_processed_per_iteration = 16;
+/** Input data sets **/
+const auto ElementwisePowerFP16Dataset = combine(combine(framework::dataset::make("DataType", DataType::F16), framework::dataset::make("DataType", DataType::F16)),
+ framework::dataset::make("DataType", DataType::F16));
+const auto ElementwisePowerFP32Dataset = combine(combine(framework::dataset::make("DataType", DataType::F32), framework::dataset::make("DataType", DataType::F32)),
+ framework::dataset::make("DataType", DataType::F32));
+} // namespace
+
+TEST_SUITE(CL)
+TEST_SUITE(ElementwisePower)
+
+// *INDENT-OFF*
+// clang-format off
+DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(
+ framework::dataset::make("Input1Info", { TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F32),
+ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F16),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Window shrink
+ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::U8), // Invalid data type combination
+ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F32), // Mismatching shapes
+ }),
+ framework::dataset::make("Input2Info",{ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F32),
+ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F16),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32),
+ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::S16),
+ TensorInfo(TensorShape(48U, 11U, 2U), 1, DataType::F32),
+ })),
+ framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F32),
+ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F16),
+ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32),
+ TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::U8),
+ TensorInfo(TensorShape(48U, 11U, 2U), 1, DataType::F32),
+ })),
+ framework::dataset::make("Expected", { true, true, false, false, false})),
+ input1_info, input2_info, output_info, expected)
+{
+ ARM_COMPUTE_EXPECT(bool(CLElementwisePower::validate(&input1_info.clone()->set_is_resizable(false), &input2_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false))) == expected, framework::LogLevel::ERRORS);
+}
+// clang-format on
+// *INDENT-ON*
+
+template <typename T>
+using CLElementwisePowerFixture = ElementwisePowerValidationFixture<CLTensor, CLAccessor, CLElementwisePower, T>;
+
+template <typename T>
+using CLElementwisePowerBroadcastFixture = ElementwisePowerBroadcastValidationFixture<CLTensor, CLAccessor, CLElementwisePower, T>;
+
+TEST_SUITE(Float)
+TEST_SUITE(FP16)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLElementwisePowerFixture<half>, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), ElementwisePowerFP16Dataset))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference, tolerance_fp16, 0.01);
+}
+
+FIXTURE_DATA_TEST_CASE(RunSmallBroadcast, CLElementwisePowerBroadcastFixture<half>, framework::DatasetMode::ALL, combine(datasets::SmallShapesBroadcast(),
+ ElementwisePowerFP16Dataset))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference, tolerance_fp16, 0.01);
+}
+TEST_SUITE_END() //FP16
+
+TEST_SUITE(FP32)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLElementwisePowerFixture<float>, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), ElementwisePowerFP32Dataset))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference, tolerance_fp32);
+}
+
+FIXTURE_DATA_TEST_CASE(RunSmallBroadcast, CLElementwisePowerBroadcastFixture<float>, framework::DatasetMode::ALL, combine(datasets::SmallShapesBroadcast(),
+ ElementwisePowerFP32Dataset))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference, tolerance_fp32);
+}
+TEST_SUITE_END() // FP32
+TEST_SUITE_END() // Float
+TEST_SUITE_END() // ElementwisePower
+TEST_SUITE_END() // CL
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/utils/TypePrinter.h b/utils/TypePrinter.h
index 62edea344a..2f9f8cba68 100644
--- a/utils/TypePrinter.h
+++ b/utils/TypePrinter.h
@@ -1394,6 +1394,9 @@ inline ::std::ostream &operator<<(::std::ostream &os, const ArithmeticOperation
case ArithmeticOperation::SQUARED_DIFF:
os << "SQUARED_DIFF";
break;
+ case ArithmeticOperation::POWER:
+ os << "POWER";
+ break;
default:
ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
}