From 047945d908b3fb51be6931bd8967213be9c8a3f7 Mon Sep 17 00:00:00 2001 From: Hyeongseok Oh Date: Tue, 1 Sep 2020 16:38:17 +0900 Subject: [PATCH] [onert/cpu] Support erf operation (#4035) - base_loader loader CUSTOM(erf) - CPU backend support Erf float32 operation Signed-off-by: Hyeongseok Oh --- compute/cker/include/cker/operation/Erf.h | 42 ++++++++++++++++++++++ runtime/onert/backend/cpu/KernelGenerator.cc | 2 ++ .../onert/backend/cpu/ops/ElementwiseUnaryLayer.cc | 17 +++++++++ .../onert/backend/cpu/ops/ElementwiseUnaryLayer.h | 1 + .../core/include/ir/operation/ElementwiseUnary.h | 1 + .../core/src/ir/operation/ElementwiseUnary.cc | 1 + .../frontend/base_loader/include/base_loader.h | 7 +++- 7 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 compute/cker/include/cker/operation/Erf.h diff --git a/compute/cker/include/cker/operation/Erf.h b/compute/cker/include/cker/operation/Erf.h new file mode 100644 index 0000000..a9be365 --- /dev/null +++ b/compute/cker/include/cker/operation/Erf.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_CKER_ERF_H__ +#define __NNFW_CKER_ERF_H__ + +#include "cker/Shape.h" + +#include + +namespace nnfw +{ +namespace cker +{ + +inline void Erf(const Shape &input_shape, const float *input_data, const Shape &output_shape, + float *output_data) +{ + const int size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < size; i++) + { + output_data[i] = std::erf(input_data[i]); + } +} + +} // namespace cker +} // namespace nnfw + +#endif // __NNFW_CKER_ERF_H__ diff --git a/runtime/onert/backend/cpu/KernelGenerator.cc b/runtime/onert/backend/cpu/KernelGenerator.cc index 38e0689..74b6f0c 100644 --- a/runtime/onert/backend/cpu/KernelGenerator.cc +++ b/runtime/onert/backend/cpu/KernelGenerator.cc @@ -143,6 +143,8 @@ ops::ElementwiseUnaryType convertElementwiseUnaryType(ir::operation::Elementwise return ops::ElementwiseUnaryType::kCast; case ir::operation::ElementwiseUnary::Type::COS: return ops::ElementwiseUnaryType::kCos; + case ir::operation::ElementwiseUnary::Type::ERF: + return ops::ElementwiseUnaryType::kErf; case ir::operation::ElementwiseUnary::Type::EXP: return ops::ElementwiseUnaryType::kExp; case ir::operation::ElementwiseUnary::Type::LOG: diff --git a/runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.cc b/runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.cc index d1d9e6a..f8f89ab 100644 --- a/runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.cc +++ b/runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.cc @@ -19,6 +19,7 @@ #include "OperationUtils.h" #include +#include #include #include #include @@ -123,6 +124,12 @@ void expFloat32(const IPortableTensor *input, IPortableTensor *output) getTensorShape(output), reinterpret_cast(output->buffer())); } +void erfFloat32(const IPortableTensor *input, IPortableTensor *output) +{ + nnfw::cker::Erf(getTensorShape(input), reinterpret_cast(input->buffer()), + getTensorShape(output), reinterpret_cast(output->buffer())); +} + void logFloat32(const IPortableTensor *input, IPortableTensor *output) { nnfw::cker::Log(getTensorShape(input), reinterpret_cast(input->buffer()), @@ -222,6 +229,16 @@ void ElementwiseUnaryLayer::configure(const IPortableTensor *input, IPortableTen throw std::runtime_error{"Exp: Unsupported data type"}; } break; + case ElementwiseUnaryType::kErf: + if ((input->data_type() == OperandType::FLOAT32)) + { + _kernel = erfFloat32; + } + else + { + throw std::runtime_error{"Exp: Unsupported data type"}; + } + break; case ElementwiseUnaryType::kLog: if ((input->data_type() == OperandType::FLOAT32)) { diff --git a/runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.h b/runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.h index b489c7d..7496838 100644 --- a/runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.h +++ b/runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.h @@ -35,6 +35,7 @@ enum class ElementwiseUnaryType kAbs, kCast, kCos, + kErf, kExp, kLog, kLogicalNot, diff --git a/runtime/onert/core/include/ir/operation/ElementwiseUnary.h b/runtime/onert/core/include/ir/operation/ElementwiseUnary.h index 32295ec..c40778a 100644 --- a/runtime/onert/core/include/ir/operation/ElementwiseUnary.h +++ b/runtime/onert/core/include/ir/operation/ElementwiseUnary.h @@ -40,6 +40,7 @@ public: CAST, COS, DEQUANTIZE, + ERF, EXP, FLOOR, LOG, diff --git a/runtime/onert/core/src/ir/operation/ElementwiseUnary.cc b/runtime/onert/core/src/ir/operation/ElementwiseUnary.cc index bd25e57..7dfcd4a 100644 --- a/runtime/onert/core/src/ir/operation/ElementwiseUnary.cc +++ b/runtime/onert/core/src/ir/operation/ElementwiseUnary.cc @@ -44,6 +44,7 @@ std::string ElementwiseUnary::name() const {ElementwiseUnaryType::CAST, std::string{"Cast"}}, {ElementwiseUnaryType::COS, std::string{"Cos"}}, {ElementwiseUnaryType::DEQUANTIZE, std::string{"Dequantize"}}, + {ElementwiseUnaryType::ERF, std::string{"Erf"}}, {ElementwiseUnaryType::EXP, std::string{"Exp"}}, {ElementwiseUnaryType::FLOOR, std::string{"Floor"}}, {ElementwiseUnaryType::LOG, std::string{"Log"}}, diff --git a/runtime/onert/frontend/base_loader/include/base_loader.h b/runtime/onert/frontend/base_loader/include/base_loader.h index 9888910..480452e 100644 --- a/runtime/onert/frontend/base_loader/include/base_loader.h +++ b/runtime/onert/frontend/base_loader/include/base_loader.h @@ -1207,7 +1207,8 @@ void BaseLoader::loadCustom(const Operator *op, ir Einsum, BroadcastTo, FusedBatchNorm, - StatelessRandomUniform + StatelessRandomUniform, + Erf }; // Mapping from custom op name string to BuiltinOP enum @@ -1220,6 +1221,7 @@ void BaseLoader::loadCustom(const Operator *op, ir {"FusedBatchNormV3", BuiltinOP::FusedBatchNorm}, {"BroadcastTo", BuiltinOP::BroadcastTo}, {"StatelessRandomUniform", BuiltinOP::StatelessRandomUniform}, + {"Erf", BuiltinOP::Erf}, }; try @@ -1252,6 +1254,9 @@ void BaseLoader::loadCustom(const Operator *op, ir case BuiltinOP::StatelessRandomUniform: loadStatelessRandomUniform(op, subg); break; + case BuiltinOP::Erf: + loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ERF); + break; default: throw std::runtime_error{ "Loader: Custom OP map is defined but operation loader function is not defined"}; -- 2.7.4