From d6b8a71714361881a249a6f6ed67125f290f4a83 Mon Sep 17 00:00:00 2001 From: Jonathan Deakin Date: Tue, 23 Aug 2022 11:44:18 +0100 Subject: =?UTF-8?q?Add=20FP32=20Neon=E2=84=A2=20swish=20activation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id37b59adbc8c4cbe218d1652aeb02a0b4ce42c66 Signed-off-by: Jonathan Deakin Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/8256 Tested-by: Arm Jenkins Reviewed-by: Pablo Marquez Tello Comments-Addressed: Arm Jenkins Benchmark: Arm Jenkins --- arm_compute/core/Types.h | 3 ++- src/core/Utils.cpp | 1 + src/cpu/kernels/activation/generic/neon/impl.h | 6 ++++++ src/cpu/kernels/activation/generic/sve/fp16.cpp | 5 ++++- src/cpu/kernels/activation/generic/sve/fp32.cpp | 3 +++ tests/validation/NEON/ActivationLayer.cpp | 5 ++++- tests/validation/reference/ActivationLayer.h | 3 +++ utils/TypePrinter.h | 3 +++ 8 files changed, 26 insertions(+), 3 deletions(-) diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h index 36dba2cc00..fc6d46c53b 100644 --- a/arm_compute/core/Types.h +++ b/arm_compute/core/Types.h @@ -1641,7 +1641,8 @@ public: SQRT, /**< Square root ( \f$ f(x) = \sqrt{x} \f$ )*/ LINEAR, /**< Linear ( \f$ f(x)= ax + b \f$ ) */ IDENTITY, /**< Identity ( \f$ f(x)= x \f$ ) */ - HARD_SWISH, /**< Hard-swish ( \f$ f(x) = (x * relu6(x+3))/6 \f$ ) */ + HARD_SWISH, /**< Hard-swish ( \f$ f(x) = (x \text{ReLU6}(x+3))/6 = x \min(\max(0,x+3),6)/6 \f$ ) */ + SWISH, /**< Swish ( \f$ f(x) = \frac{x}{1 + e^{-ax}} = x \text{logistic}(ax) \f$ ) */ GELU /**< GELU ( \f$ f(x) = x * 1/2 * 1 + erf(x / \sqrt{2}) \f$ ) */ }; diff --git a/src/core/Utils.cpp b/src/core/Utils.cpp index 48eb8b9bf5..d05a044fc8 100644 --- a/src/core/Utils.cpp +++ b/src/core/Utils.cpp @@ -178,6 +178,7 @@ const std::string &string_from_activation_func(ActivationLayerInfo::ActivationFu { ActivationLayerInfo::ActivationFunction::TANH, "TANH" }, { ActivationLayerInfo::ActivationFunction::IDENTITY, "IDENTITY" }, { ActivationLayerInfo::ActivationFunction::HARD_SWISH, "HARD_SWISH" }, + { ActivationLayerInfo::ActivationFunction::SWISH, "SWISH" }, { ActivationLayerInfo::ActivationFunction::GELU, "GELU" } }; diff --git a/src/cpu/kernels/activation/generic/neon/impl.h b/src/cpu/kernels/activation/generic/neon/impl.h index 4d4aa8d212..4f392866b5 100644 --- a/src/cpu/kernels/activation/generic/neon/impl.h +++ b/src/cpu/kernels/activation/generic/neon/impl.h @@ -149,6 +149,9 @@ void fp_neon_activation_impl(const ITensor *src, ITensor *dst, const ActivationL case ActivationLayerInfo::ActivationFunction::HARD_SWISH: tmp = wrapper::vmul(vin, wrapper::vmul(const_inv_6, wrapper::vmin(const_6, wrapper::vmax(const_0, wrapper::vadd(vin, const_3))))); break; + case ActivationLayerInfo::ActivationFunction::SWISH: + tmp = wrapper::vmul(vin, wrapper::vinv(wrapper::vadd(const_1, wrapper::vexpq(wrapper::vneg(wrapper::vmul(va, vin)))))); + break; #ifdef __aarch64__ case ActivationLayerInfo::ActivationFunction::GELU: tmp = wrapper::vmul(vin, wrapper::vmul(const_inv_2, wrapper::vadd(const_1, wrapper::verf(wrapper::vmul(vin, const_inv_sqrt_2))))); @@ -208,6 +211,9 @@ void fp_neon_activation_impl(const ITensor *src, ITensor *dst, const ActivationL case ActivationLayerInfo::ActivationFunction::HARD_SWISH: tmp = in * ((std::min(std::max((in + 3), 0.0f), 6.0f)) * 0.166666667f); break; + case ActivationLayerInfo::ActivationFunction::SWISH: + tmp = in / (static_cast(1) + std::exp(-a*in)); + break; case ActivationLayerInfo::ActivationFunction::GELU: tmp = in * static_cast(0.5f * (1.0f + erff(static_cast(in) / 1.41421356237f))); break; diff --git a/src/cpu/kernels/activation/generic/sve/fp16.cpp b/src/cpu/kernels/activation/generic/sve/fp16.cpp index 5730a361d9..6e9648b5bf 100644 --- a/src/cpu/kernels/activation/generic/sve/fp16.cpp +++ b/src/cpu/kernels/activation/generic/sve/fp16.cpp @@ -114,6 +114,9 @@ void sve_fp16_activation(const ITensor *src, ITensor *dst, const ActivationLayer case ActivationLayerInfo::ActivationFunction::HARD_SWISH: tmp = svmul_f16_z(pg, vin, svmul_f16_z(pg, const_inv_6, svmin_f16_z(pg, const_6, svmax_f16_z(pg, const_0, svadd_f16_z(pg, vin, const_3))))); break; + case ActivationLayerInfo::ActivationFunction::SWISH: + tmp = svmul_f16_z(pg, vin, svinv_f16_z(pg, svadd_f16_z(pg, const_1, svexp_f16_z(pg, svneg_f16_z(pg, svmul_f16_z(pg, va, vin)))))); + break; default: ARM_COMPUTE_ERROR("Unsupported activation function"); } @@ -129,4 +132,4 @@ void sve_fp16_activation(const ITensor *src, ITensor *dst, const ActivationLayer } } // namespace cpu } // namespace arm_compute -#endif /* defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(ENABLE_FP16_KERNELS) */ \ No newline at end of file +#endif /* defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(ENABLE_FP16_KERNELS) */ diff --git a/src/cpu/kernels/activation/generic/sve/fp32.cpp b/src/cpu/kernels/activation/generic/sve/fp32.cpp index 7ce2046730..b5490063cf 100644 --- a/src/cpu/kernels/activation/generic/sve/fp32.cpp +++ b/src/cpu/kernels/activation/generic/sve/fp32.cpp @@ -113,6 +113,9 @@ void sve_fp32_activation(const ITensor *src, ITensor *dst, const ActivationLayer case ActivationLayerInfo::ActivationFunction::HARD_SWISH: tmp = svmul_f32_z(pg, vin, svmul_f32_z(pg, const_inv_6, svmin_f32_z(pg, const_6, svmax_f32_z(pg, const_0, svadd_f32_z(pg, vin, const_3))))); break; + case ActivationLayerInfo::ActivationFunction::SWISH: + tmp = svmul_f32_z(pg, vin, svinv_f32_z(pg, svadd_f32_z(pg, const_1, svexp_f32_z(pg, svneg_f32_z(pg, svmul_f32_z(pg, va, vin)))))); + break; default: ARM_COMPUTE_ERROR("Unsupported activation function"); } diff --git a/tests/validation/NEON/ActivationLayer.cpp b/tests/validation/NEON/ActivationLayer.cpp index a2971f28ba..d580a1c2ca 100644 --- a/tests/validation/NEON/ActivationLayer.cpp +++ b/tests/validation/NEON/ActivationLayer.cpp @@ -68,6 +68,7 @@ RelativeTolerance relative_tolerance(DataType data_type, ActivationLayerI case ActivationLayerInfo::ActivationFunction::SQRT: case ActivationLayerInfo::ActivationFunction::TANH: case ActivationLayerInfo::ActivationFunction::HARD_SWISH: + case ActivationLayerInfo::ActivationFunction::SWISH: case ActivationLayerInfo::ActivationFunction::GELU: switch(data_type) { @@ -111,6 +112,7 @@ AbsoluteTolerance absolute_tolerance(DataType data_type, ActivationLayerI case ActivationLayerInfo::ActivationFunction::LOGISTIC: case ActivationLayerInfo::ActivationFunction::SQRT: case ActivationLayerInfo::ActivationFunction::TANH: + case ActivationLayerInfo::ActivationFunction::SWISH: case ActivationLayerInfo::ActivationFunction::HARD_SWISH: switch(data_type) { @@ -173,7 +175,8 @@ const auto CNNDataTypes = framework::dataset::make("DataType", DataType::F32, }); -const auto NeonActivationFunctionsDataset = concat(datasets::ActivationFunctions(), framework::dataset::make("ActivationFunction", ActivationLayerInfo::ActivationFunction::HARD_SWISH)); +const auto NeonActivationFunctionsDataset = concat(datasets::ActivationFunctions(), + framework::dataset::make("ActivationFunction", {ActivationLayerInfo::ActivationFunction::HARD_SWISH, ActivationLayerInfo::ActivationFunction::SWISH})); /** Input data sets. */ const auto ActivationDataset = combine(combine(framework::dataset::make("InPlace", { false, true }), NeonActivationFunctionsDataset), framework::dataset::make("AlphaBeta", { 0.5f, 1.f })); diff --git a/tests/validation/reference/ActivationLayer.h b/tests/validation/reference/ActivationLayer.h index 97733238ef..2bf96831a6 100644 --- a/tests/validation/reference/ActivationLayer.h +++ b/tests/validation/reference/ActivationLayer.h @@ -84,6 +84,9 @@ inline T activate_float(T x, T a, T b, ActivationLayerInfo::ActivationFunction a case ActivationLayerInfo::ActivationFunction::HARD_SWISH: ret = x * ((std::min(std::max(static_cast(x + 3), static_cast(0.0f)), static_cast(6.0f))) * 0.166666667f); break; + case ActivationLayerInfo::ActivationFunction::SWISH: + ret = static_cast(x) / (static_cast(1) + std::exp(-a*x)); + break; case ActivationLayerInfo::ActivationFunction::GELU: ret = x * 0.5f * (1 + erf(x / std::sqrt(2.0f))); break; diff --git a/utils/TypePrinter.h b/utils/TypePrinter.h index 21f9c0849c..f55f72a4b8 100644 --- a/utils/TypePrinter.h +++ b/utils/TypePrinter.h @@ -628,6 +628,9 @@ inline ::std::ostream &operator<<(::std::ostream &os, const ActivationLayerInfo: case ActivationLayerInfo::ActivationFunction::HARD_SWISH: os << "HARD_SWISH"; break; + case ActivationLayerInfo::ActivationFunction::SWISH: + os << "SWISH"; + break; case ActivationLayerInfo::ActivationFunction::GELU: os << "GELU"; break; -- cgit v1.2.1