aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgios Pinitas <georgios.pinitas@arm.com>2021-08-03 08:24:00 +0100
committerSheri Zhang <sheri.zhang@arm.com>2021-08-04 08:56:33 +0000
commit4164814a099773c0a512889473c980bc148e590f (patch)
tree7ee27bbd40724635f5bf22bc9ec28b3a1a4d1ac9
parent6e90c12e3067c482524a08bf322f42de6d9d27b9 (diff)
downloadComputeLibrary-4164814a099773c0a512889473c980bc148e590f.tar.gz
Implement Operator API
Resolves: COMPMID-4512 Signed-off-by: Georgios Pinitas <georgios.pinitas@arm.com> Change-Id: Id12130365fa3fe2261160931dcc7affb6b467186 Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/6031 Tested-by: Arm Jenkins <bsgcomp@arm.com> Reviewed-by: Michele Di Giorgio <michele.digiorgio@arm.com> Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
-rw-r--r--Android.bp2
-rw-r--r--SConscript1
-rw-r--r--arm_compute/Acl.hpp19
-rw-r--r--arm_compute/AclDescriptors.h9
-rw-r--r--filelist.json7
-rw-r--r--src/c/AclContext.cpp6
-rw-r--r--src/c/operators/AclActivation.cpp49
-rw-r--r--src/common/IContext.h13
-rw-r--r--src/common/IOperator.cpp73
-rw-r--r--src/common/IOperator.h72
-rw-r--r--src/common/Types.h1
-rw-r--r--src/common/utils/LegacySupport.cpp54
-rw-r--r--src/common/utils/LegacySupport.h8
-rw-r--r--src/cpu/CpuContext.h4
-rw-r--r--src/gpu/cl/ClContext.h4
-rw-r--r--src/runtime/cpu/operators/CpuActivation.cpp28
-rw-r--r--src/runtime/gpu/cl/operators/ClActivation.cpp35
-rw-r--r--tests/validation/NEON/ActivationLayer.cpp43
18 files changed, 369 insertions, 59 deletions
diff --git a/Android.bp b/Android.bp
index 6b1c3c56c4..3a3f1db334 100644
--- a/Android.bp
+++ b/Android.bp
@@ -60,7 +60,9 @@ cc_library_static {
"src/c/AclTensorPack.cpp",
"src/c/AclVersion.cpp",
"src/c/cl/AclOpenClExt.cpp",
+ "src/c/operators/AclActivation.cpp",
"src/common/AllocatorWrapper.cpp",
+ "src/common/IOperator.cpp",
"src/common/ITensorV2.cpp",
"src/common/TensorPack.cpp",
"src/common/cpuinfo/CpuInfo.cpp",
diff --git a/SConscript b/SConscript
index 682f55310e..672ba0f39d 100644
--- a/SConscript
+++ b/SConscript
@@ -406,6 +406,7 @@ runtime_files = Glob('src/runtime/CPP/functions/*.cpp')
# C API files
runtime_files_hp += filelist['c_api']['common']
+runtime_files_hp += filelist['c_api']['operators']
if env['opencl']:
runtime_files_hp += filelist['c_api']['gpu']
diff --git a/arm_compute/Acl.hpp b/arm_compute/Acl.hpp
index 7791c5633e..55e04e876d 100644
--- a/arm_compute/Acl.hpp
+++ b/arm_compute/Acl.hpp
@@ -87,6 +87,7 @@ OBJECT_DELETER(AclContext, AclDestroyContext)
OBJECT_DELETER(AclQueue, AclDestroyQueue)
OBJECT_DELETER(AclTensor, AclDestroyTensor)
OBJECT_DELETER(AclTensorPack, AclDestroyTensorPack)
+OBJECT_DELETER(AclOperator, AclDestroyOperator)
#undef OBJECT_DELETER
@@ -773,6 +774,24 @@ protected:
/** Constructor */
Operator() = default;
};
+
+/// Operators
+using ActivationDesc = AclActivationDescriptor;
+class Activation : public Operator
+{
+public:
+ Activation(Context &ctx, const TensorDescriptor &src, const TensorDescriptor &dst, const ActivationDesc &desc, StatusCode *status = nullptr)
+ {
+ AclOperator op;
+ const auto st = detail::as_enum<StatusCode>(AclActivation(&op, ctx.get(), src.get(), dst.get(), desc));
+ reset(op);
+ report_status(st, "[Compute Library] Failure during Activation operator creation");
+ if(status)
+ {
+ *status = st;
+ }
+ }
+};
} // namespace acl
#undef ARM_COMPUTE_IGNORE_UNUSED
#endif /* ARM_COMPUTE_ACL_HPP_ */
diff --git a/arm_compute/AclDescriptors.h b/arm_compute/AclDescriptors.h
index 7b7655e9c7..a564bd2141 100644
--- a/arm_compute/AclDescriptors.h
+++ b/arm_compute/AclDescriptors.h
@@ -40,7 +40,7 @@ typedef enum
AclLuBoundedRelu = 6, /**< Lower and Upper Bounded Rectifier */
AclLeakyRelu = 7, /**< Leaky Rectifier */
AclSoftRelu = 8, /**< Soft Rectifier */
- AclSoftElu = 9, /**< Exponential Linear Unit */
+ AclElu = 9, /**< Exponential Linear Unit */
AclAbs = 10, /**< Absolute */
AclSquare = 11, /**< Square */
AclSqrt = 12, /**< Square root */
@@ -51,9 +51,10 @@ typedef enum
/**< Activation layer descriptor */
typedef struct
{
- AclActivationType type; /**< Activation type */
- float a; /**< Factor &alpha used by some activations */
- float b; /**< Factor &beta used by some activations */
+ AclActivationType type; /**< Activation type */
+ float a; /**< Factor &alpha used by some activations */
+ float b; /**< Factor &beta used by some activations */
+ bool inplace; /**< Hint that src and dst tensors will be the same */
} AclActivationDescriptor;
#ifdef __cplusplus
}
diff --git a/filelist.json b/filelist.json
index b426411681..c5abc620cd 100644
--- a/filelist.json
+++ b/filelist.json
@@ -6,7 +6,8 @@
"src/common/utils/LegacySupport.cpp",
"src/common/AllocatorWrapper.cpp",
"src/common/ITensorV2.cpp",
- "src/common/TensorPack.cpp"
+ "src/common/TensorPack.cpp",
+ "src/common/IOperator.cpp"
],
"c_api": {
"common": [
@@ -21,6 +22,10 @@
],
"gpu": [
"src/c/cl/AclOpenClExt.cpp"
+ ],
+ "operators":
+ [
+ "src/c/operators/AclActivation.cpp"
]
},
"gpu": {
diff --git a/src/c/AclContext.cpp b/src/c/AclContext.cpp
index c62e627edc..dbf2a3df88 100644
--- a/src/c/AclContext.cpp
+++ b/src/c/AclContext.cpp
@@ -75,7 +75,7 @@ arm_compute::IContext *create_context(AclTarget target, const AclContextOptions
}
} // namespace
-extern "C" AclStatus AclCreateContext(AclContext *ctx,
+extern "C" AclStatus AclCreateContext(AclContext *external_ctx,
AclTarget target,
const AclContextOptions *options)
{
@@ -91,13 +91,13 @@ extern "C" AclStatus AclCreateContext(AclContext *ctx,
return AclInvalidArgument;
}
- auto acl_ctx = create_context(target, options);
+ auto ctx = create_context(target, options);
if(ctx == nullptr)
{
ARM_COMPUTE_LOG_ERROR_WITH_FUNCNAME_ACL("Couldn't allocate internal resources for context creation!");
return AclOutOfMemory;
}
- *ctx = acl_ctx;
+ *external_ctx = ctx;
return AclSuccess;
}
diff --git a/src/c/operators/AclActivation.cpp b/src/c/operators/AclActivation.cpp
new file mode 100644
index 0000000000..bf604ee2dd
--- /dev/null
+++ b/src/c/operators/AclActivation.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 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/AclOperators.h"
+
+#include "src/common/IOperator.h"
+#include "src/common/utils/Macros.h"
+#include "src/common/utils/Validate.h"
+
+extern "C" AclStatus AclActivation(AclOperator *external_op,
+ AclContext external_ctx,
+ const AclTensorDescriptor *src,
+ const AclTensorDescriptor *dst,
+ const AclActivationDescriptor info)
+{
+ using namespace arm_compute;
+
+ // Extract internal context
+ auto ctx = get_internal(external_ctx);
+ StatusCode status = detail::validate_internal_context(ctx);
+ ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);
+
+ bool is_validate = (external_op == ARM_COMPUTE_VALIDATE_OPERATOR_SUPPORT);
+
+ std::tie(*external_op, status) = ctx->create_activation(*src, *dst, info, is_validate);
+ ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);
+
+ return AclSuccess;
+} \ No newline at end of file
diff --git a/src/common/IContext.h b/src/common/IContext.h
index 31f39da06d..1ae46c57de 100644
--- a/src/common/IContext.h
+++ b/src/common/IContext.h
@@ -44,6 +44,7 @@ namespace arm_compute
// Forward declarations
class ITensorV2;
class IQueue;
+class IOperator;
/**< Context interface */
class IContext : public AclContext_
@@ -53,13 +54,11 @@ public:
: AclContext_(), _target(target), _refcount(0)
{
}
-
/** Virtual Destructor */
virtual ~IContext()
{
header.type = detail::ObjectType::Invalid;
};
-
/** Target type accessor
*
* @return Target that the context is associated with
@@ -68,19 +67,16 @@ public:
{
return _target;
}
-
/** Increment context refcount */
void inc_ref() const
{
++_refcount;
}
-
/** Decrement context refcount */
void dec_ref() const
{
--_refcount;
}
-
/** Reference counter accessor
*
* @return The number of references pointing to this object
@@ -89,7 +85,6 @@ public:
{
return _refcount;
}
-
/** Checks if an object is valid
*
* @return True if sucessful otherwise false
@@ -98,7 +93,6 @@ public:
{
return header.type == detail::ObjectType::Context;
}
-
/** Create a tensor object
*
* @param[in] desc Descriptor to use
@@ -107,7 +101,6 @@ public:
* @return A pointer to the created tensor object
*/
virtual ITensorV2 *create_tensor(const AclTensorDescriptor &desc, bool allocate) = 0;
-
/** Create a queue object
*
* @param[in] options Queue options to be used
@@ -115,6 +108,10 @@ public:
* @return A pointer to the created queue object
*/
virtual IQueue *create_queue(const AclQueueOptions *options) = 0;
+ virtual std::tuple<IOperator *, StatusCode> create_activation(const AclTensorDescriptor &src,
+ const AclTensorDescriptor &dst,
+ const AclActivationDescriptor &act,
+ bool is_validate) = 0;
private:
Target _target; /**< Target type of context */
diff --git a/src/common/IOperator.cpp b/src/common/IOperator.cpp
new file mode 100644
index 0000000000..b56f0e97fb
--- /dev/null
+++ b/src/common/IOperator.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021 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 "src/common/IOperator.h"
+#include "src/common/utils/Validate.h"
+
+namespace arm_compute
+{
+#ifndef DOXYGEN_SKIP_THIS
+IOperator::IOperator(IContext *ctx)
+ : AclOperator_()
+{
+ ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx);
+ this->header.ctx = ctx;
+ this->header.ctx->inc_ref();
+}
+
+IOperator::~IOperator()
+{
+ this->header.ctx->dec_ref();
+ this->header.type = detail::ObjectType::Invalid;
+}
+
+bool IOperator::is_valid() const
+{
+ return this->header.type == detail::ObjectType::Operator;
+}
+
+StatusCode IOperator::run(ITensorPack &tensors)
+{
+ _op->run(tensors);
+ return StatusCode::Success;
+}
+
+StatusCode IOperator::run(IQueue &queue, ITensorPack &tensors)
+{
+ ARM_COMPUTE_UNUSED(queue);
+ _op->run(tensors);
+ return StatusCode::Success;
+}
+
+StatusCode IOperator::prepare(ITensorPack &tensors)
+{
+ _op->prepare(tensors);
+ return StatusCode::Success;
+}
+
+MemoryRequirements IOperator::workspace() const
+{
+ return _op->workspace();
+}
+#endif /* DOXYGEN_SKIP_THIS */
+} // namespace arm_compute
diff --git a/src/common/IOperator.h b/src/common/IOperator.h
index 7fdb443acb..1b65a09e0d 100644
--- a/src/common/IOperator.h
+++ b/src/common/IOperator.h
@@ -27,6 +27,11 @@
#include "src/common/IContext.h"
#include "src/common/IQueue.h"
+// TODO: Remove when all functions have been ported
+#include "arm_compute/core/experimental/Types.h"
+#include "arm_compute/runtime/IOperator.h"
+#include "src/common/utils/Validate.h"
+
#include <vector>
struct AclOperator_
@@ -42,21 +47,12 @@ namespace arm_compute
{
// Forward declarations
class ITensorPack;
-
-/** Structure to capture internally memory requirements */
-struct MemoryInfo
+namespace experimental
{
- MemoryInfo(AclTensorSlot slot_id, size_t size, size_t alignment) noexcept
- : slot_id(slot_id),
- size(size),
- alignment(alignment)
- {
- }
- AclTensorSlot slot_id;
- size_t size;
- size_t alignment;
-};
-using MemoryRequirements = std::vector<MemoryInfo>;
+class IOperator;
+} // namespace experimental
+
+using MemoryRequirements = experimental::MemoryRequirements;
/** Base class specifying the operator interface */
class IOperator : public AclOperator_
@@ -66,55 +62,45 @@ public:
*
* @param[in] ctx Context to be used by the operator
*/
- explicit IOperator(IContext *ctx)
- {
- this->header.ctx = ctx;
- this->header.ctx->inc_ref();
- }
-
+ explicit IOperator(IContext *ctx);
/** Destructor */
- virtual ~IOperator()
- {
- this->header.ctx->dec_ref();
- this->header.type = detail::ObjectType::Invalid;
- };
-
+ virtual ~IOperator();
/** Checks if an operator is valid
*
* @return True if successful otherwise false
*/
- bool is_valid() const
- {
- return this->header.type == detail::ObjectType::Operator;
- };
-
+ bool is_valid() const;
/** Run the kernels contained in the function
*
- * @param[in] queue Queue to run a kernel on
+ * @param[in] queue Queue to use
* @param[in] tensors Vector that contains the tensors to operate on
*/
- virtual StatusCode run(IQueue &queue, ITensorPack &tensors) = 0;
-
+ virtual StatusCode run(IQueue &queue, ITensorPack &tensors);
+ /** Run the kernels contained in the function
+ *
+ * @param[in] tensors Vector that contains the tensors to operate on
+ */
+ virtual StatusCode run(ITensorPack &tensors);
/** Prepare the operator for execution
*
* Any one off pre-processing step required by the function is handled here
*
- * @param[in] constants Vector that contains the constants tensors.
+ * @param[in] tensors Vector that contains the preparation tensors.
*
* @note Prepare stage might not need all the function's buffers' backing memory to be available in order to execute
*/
- virtual StatusCode prepare(ITensorPack &constants)
- {
- ARM_COMPUTE_UNUSED(constants);
- return StatusCode::Success;
- }
-
+ virtual StatusCode prepare(ITensorPack &tensors);
/** Return the memory requirements required by the workspace
*/
- virtual MemoryRequirements workspace() const
+ virtual MemoryRequirements workspace() const;
+
+ void set_internal_operator(std::unique_ptr<experimental::IOperator> op)
{
- return {};
+ _op = std::move(op);
}
+
+private:
+ std::unique_ptr<experimental::IOperator> _op{ nullptr };
};
/** Extract internal representation of an Operator
diff --git a/src/common/Types.h b/src/common/Types.h
index ba07b51d55..25ee32353a 100644
--- a/src/common/Types.h
+++ b/src/common/Types.h
@@ -24,6 +24,7 @@
#ifndef SRC_COMMON_TYPES_H_
#define SRC_COMMON_TYPES_H_
+#include "arm_compute/AclDescriptors.h"
#include "arm_compute/AclTypes.h"
namespace arm_compute
diff --git a/src/common/utils/LegacySupport.cpp b/src/common/utils/LegacySupport.cpp
index 569b2abd89..6623825124 100644
--- a/src/common/utils/LegacySupport.cpp
+++ b/src/common/utils/LegacySupport.cpp
@@ -107,5 +107,59 @@ AclTensorDescriptor convert_to_descriptor(const TensorInfo &info)
};
return desc;
}
+
+ActivationLayerInfo convert_to_activation_info(const AclActivationDescriptor &desc)
+{
+ ActivationLayerInfo::ActivationFunction act;
+ switch(desc.type)
+ {
+ case AclActivationType::AclIdentity:
+ act = ActivationLayerInfo::ActivationFunction::IDENTITY;
+ break;
+ case AclActivationType::AclLogistic:
+ act = ActivationLayerInfo::ActivationFunction::LOGISTIC;
+ break;
+ case AclActivationType::AclTanh:
+ act = ActivationLayerInfo::ActivationFunction::TANH;
+ break;
+ case AclActivationType::AclRelu:
+ act = ActivationLayerInfo::ActivationFunction::RELU;
+ break;
+ case AclActivationType::AclBoundedRelu:
+ act = ActivationLayerInfo::ActivationFunction::BOUNDED_RELU;
+ break;
+ case AclActivationType::AclLuBoundedRelu:
+ act = ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU;
+ break;
+ case AclActivationType::AclLeakyRelu:
+ act = ActivationLayerInfo::ActivationFunction::LEAKY_RELU;
+ break;
+ case AclActivationType::AclSoftRelu:
+ act = ActivationLayerInfo::ActivationFunction::SOFT_RELU;
+ break;
+ case AclActivationType::AclElu:
+ act = ActivationLayerInfo::ActivationFunction::ELU;
+ break;
+ case AclActivationType::AclAbs:
+ act = ActivationLayerInfo::ActivationFunction::ABS;
+ break;
+ case AclActivationType::AclSquare:
+ act = ActivationLayerInfo::ActivationFunction::SQUARE;
+ break;
+ case AclActivationType::AclSqrt:
+ act = ActivationLayerInfo::ActivationFunction::SQRT;
+ break;
+ case AclActivationType::AclLinear:
+ act = ActivationLayerInfo::ActivationFunction::LINEAR;
+ break;
+ case AclActivationType::AclHardSwish:
+ act = ActivationLayerInfo::ActivationFunction::HARD_SWISH;
+ break;
+ default:
+ return ActivationLayerInfo();
+ }
+
+ return ActivationLayerInfo(act, desc.a, desc.b);
+}
} // namespace detail
} // namespace arm_compute
diff --git a/src/common/utils/LegacySupport.h b/src/common/utils/LegacySupport.h
index c2cc1bc182..3c3b09fce6 100644
--- a/src/common/utils/LegacySupport.h
+++ b/src/common/utils/LegacySupport.h
@@ -26,6 +26,7 @@
#include "arm_compute/Acl.h"
#include "arm_compute/core/TensorInfo.h"
+#include "arm_compute/core/Types.h"
namespace arm_compute
{
@@ -45,6 +46,13 @@ TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc);
* @return A converted descriptor
*/
AclTensorDescriptor convert_to_descriptor(const TensorInfo &info);
+/** Convert an AclActivation descriptor to an internal one
+ *
+ * @param[in] desc Descriptor to convert
+ *
+ * @return Legacy tensor meta-data
+ */
+ActivationLayerInfo convert_to_activation_info(const AclActivationDescriptor &desc);
} // namespace detail
} // namespace arm_compute
diff --git a/src/cpu/CpuContext.h b/src/cpu/CpuContext.h
index 9a59af39c1..da241ed097 100644
--- a/src/cpu/CpuContext.h
+++ b/src/cpu/CpuContext.h
@@ -62,6 +62,10 @@ public:
// Inherrited methods overridden
ITensorV2 *create_tensor(const AclTensorDescriptor &desc, bool allocate) override;
IQueue *create_queue(const AclQueueOptions *options) override;
+ std::tuple<IOperator *, StatusCode> create_activation(const AclTensorDescriptor &src,
+ const AclTensorDescriptor &dst,
+ const AclActivationDescriptor &act,
+ bool is_validate) override;
private:
AllocatorWrapper _allocator;
diff --git a/src/gpu/cl/ClContext.h b/src/gpu/cl/ClContext.h
index 2a0d4ee1c8..a50b03124b 100644
--- a/src/gpu/cl/ClContext.h
+++ b/src/gpu/cl/ClContext.h
@@ -76,6 +76,10 @@ public:
// Inherrited methods overridden
ITensorV2 *create_tensor(const AclTensorDescriptor &desc, bool allocate) override;
IQueue *create_queue(const AclQueueOptions *options) override;
+ std::tuple<IOperator *, StatusCode> create_activation(const AclTensorDescriptor &src,
+ const AclTensorDescriptor &dst,
+ const AclActivationDescriptor &act,
+ bool is_validate) override;
private:
mlgo::MLGOHeuristics _mlgo_heuristics;
diff --git a/src/runtime/cpu/operators/CpuActivation.cpp b/src/runtime/cpu/operators/CpuActivation.cpp
index 7753c9601f..80667becff 100644
--- a/src/runtime/cpu/operators/CpuActivation.cpp
+++ b/src/runtime/cpu/operators/CpuActivation.cpp
@@ -23,7 +23,10 @@
*/
#include "src/runtime/cpu/operators/CpuActivation.h"
+#include "src/common/IOperator.h"
+#include "src/common/utils/LegacySupport.h"
#include "src/core/cpu/kernels/CpuActivationKernel.h"
+#include "src/cpu/CpuContext.h"
namespace arm_compute
{
@@ -40,5 +43,30 @@ Status CpuActivation::validate(const ITensorInfo *input, const ITensorInfo *outp
{
return kernels::CpuActivationKernel::validate(input, output, activation_info);
}
+
+std::tuple<IOperator *, StatusCode> CpuContext::create_activation(const AclTensorDescriptor &src, const AclTensorDescriptor &dst, const AclActivationDescriptor &act, bool is_validate)
+{
+ TensorInfo src_info = detail::convert_to_legacy_tensor_info(src);
+ TensorInfo dst_info = detail::convert_to_legacy_tensor_info(dst);
+ auto info = detail::convert_to_activation_info(act);
+
+ if(is_validate && !bool(CpuActivation::validate(&src_info.set_is_resizable(false), &dst_info.set_is_resizable(false), info)))
+ {
+ return std::make_tuple(nullptr, StatusCode::UnsupportedConfig);
+ }
+
+ auto act_op = std::make_unique<cpu::CpuActivation>();
+ act_op->configure(&src_info, &dst_info, info);
+
+ auto op = new arm_compute::IOperator(static_cast<IContext *>(this));
+ if(op == nullptr)
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("Couldn't allocate internal resources");
+ return { nullptr, StatusCode::OutOfMemory };
+ }
+ op->set_internal_operator(std::move(act_op));
+
+ return std::make_tuple(op, StatusCode::Success);
+}
} // namespace cpu
} // namespace arm_compute
diff --git a/src/runtime/gpu/cl/operators/ClActivation.cpp b/src/runtime/gpu/cl/operators/ClActivation.cpp
index 71aa57bdbd..bef42d7fae 100644
--- a/src/runtime/gpu/cl/operators/ClActivation.cpp
+++ b/src/runtime/gpu/cl/operators/ClActivation.cpp
@@ -26,6 +26,10 @@
#include "src/core/gpu/cl/ClCompileContext.h"
#include "src/core/gpu/cl/kernels/ClActivationKernel.h"
+#include "src/common/IOperator.h"
+#include "src/common/utils/LegacySupport.h"
+#include "src/gpu/cl/ClContext.h"
+
namespace arm_compute
{
namespace opencl
@@ -42,4 +46,35 @@ Status ClActivation::validate(const ITensorInfo *src, const ITensorInfo *dst, co
return kernels::ClActivationKernel::validate(src, dst, act_info);
}
} // namespace opencl
+
+namespace gpu
+{
+namespace opencl
+{
+std::tuple<IOperator *, StatusCode> ClContext::create_activation(const AclTensorDescriptor &src, const AclTensorDescriptor &dst, const AclActivationDescriptor &act, bool is_validate)
+{
+ TensorInfo src_info = detail::convert_to_legacy_tensor_info(src);
+ TensorInfo dst_info = detail::convert_to_legacy_tensor_info(dst);
+ auto info = detail::convert_to_activation_info(act);
+
+ if(is_validate && !bool(arm_compute::opencl::ClActivation::validate(&src_info.set_is_resizable(false), &dst_info.set_is_resizable(false), info)))
+ {
+ return std::make_tuple(nullptr, StatusCode::UnsupportedConfig);
+ }
+
+ auto act_op = std::make_unique<arm_compute::opencl::ClActivation>();
+ act_op->configure(CLKernelLibrary::get().get_compile_context(), &src_info, &dst_info, info);
+
+ auto op = new arm_compute::IOperator(static_cast<IContext *>(this));
+ if(op == nullptr)
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("Couldn't allocate internal resources");
+ return { nullptr, StatusCode::OutOfMemory };
+ }
+ op->set_internal_operator(std::move(act_op));
+
+ return std::make_tuple(op, StatusCode::Success);
+}
+} // namespace opencl
+} // namespace gpu
} // namespace arm_compute
diff --git a/tests/validation/NEON/ActivationLayer.cpp b/tests/validation/NEON/ActivationLayer.cpp
index 111e969bae..69fe9053d8 100644
--- a/tests/validation/NEON/ActivationLayer.cpp
+++ b/tests/validation/NEON/ActivationLayer.cpp
@@ -37,6 +37,7 @@
#include "tests/validation/Validation.h"
#include "tests/validation/fixtures/ActivationLayerFixture.h"
+#include "arm_compute/Acl.hpp"
#include "support/Requires.h"
namespace arm_compute
@@ -215,6 +216,48 @@ void test_float_sqrt_boundary_value()
TEST_SUITE(NEON)
TEST_SUITE(ActivationLayer)
+/** Test case for memory injection in @ref cpu::CpuWinogradConv2d.
+ *
+ * Configure the operator once and inject memory at run-time in multiple executions.
+ *
+ * Checks performed in order:
+ * - Both runs compute the same output
+ */
+TEST_CASE(ActivationAPI, framework::DatasetMode::ALL)
+{
+ acl::StatusCode err = acl::StatusCode::Success;
+
+ // Create context & Queue
+ acl::Context ctx(acl::Target::Cpu, &err);
+ ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
+
+ acl::Queue queue(ctx, &err);
+ ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
+
+ // Create activation operator
+ acl::TensorDescriptor src_info({ 2, 3 }, acl::DataType::Float32);
+ acl::TensorDescriptor dst_info({ 2, 3 }, acl::DataType::Float32);
+ acl::ActivationDesc desc{ AclRelu, 6.f, 0.f, false };
+
+ acl::Activation act(ctx, src_info, dst_info, desc, &err);
+ ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
+
+ // Create tensors and feed
+ acl::Tensor src(ctx, src_info, &err);
+ ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
+ acl::Tensor dst(ctx, dst_info, &err);
+ ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
+
+ acl::TensorPack pack(ctx);
+ err = pack.add(src, ACL_SRC);
+ err = pack.add(dst, ACL_DST);
+ ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
+
+ // Execute operator
+ err = act.run(queue, pack);
+ ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
+}
+
// *INDENT-OFF*
// clang-format off
DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(