From 9b328f28b401c2418245e789f9b09f6084277ad4 Mon Sep 17 00:00:00 2001 From: liuwenhao4 Date: Mon, 14 Dec 2020 19:30:05 +0800 Subject: [PATCH] add GeLU fp32 ops --- mindspore/lite/nnacl/fp32/gelu_fp32.c | 39 ++++++++ mindspore/lite/nnacl/fp32/gelu_fp32.h | 31 +++++++ mindspore/lite/nnacl/gelu_parameter.h | 28 ++++++ mindspore/lite/schema/ops.fbs | 4 + mindspore/lite/src/ops/gelu.cc | 42 +++++++++ mindspore/lite/src/ops/gelu.h | 45 ++++++++++ .../lite/src/ops/populate/gelu_populate.cc | 40 +++++++++ .../src/runtime/kernel/arm/base/gelu_base.cc | 59 +++++++++++++ .../src/runtime/kernel/arm/base/gelu_base.h | 50 +++++++++++ .../src/runtime/kernel/arm/fp32/gelu_fp32.cc | 88 +++++++++++++++++++ .../src/runtime/kernel/arm/fp32/gelu_fp32.h | 46 ++++++++++ 11 files changed, 472 insertions(+) create mode 100644 mindspore/lite/nnacl/fp32/gelu_fp32.c create mode 100644 mindspore/lite/nnacl/fp32/gelu_fp32.h create mode 100644 mindspore/lite/nnacl/gelu_parameter.h create mode 100644 mindspore/lite/src/ops/gelu.cc create mode 100644 mindspore/lite/src/ops/gelu.h create mode 100644 mindspore/lite/src/ops/populate/gelu_populate.cc create mode 100644 mindspore/lite/src/runtime/kernel/arm/base/gelu_base.cc create mode 100644 mindspore/lite/src/runtime/kernel/arm/base/gelu_base.h create mode 100644 mindspore/lite/src/runtime/kernel/arm/fp32/gelu_fp32.cc create mode 100644 mindspore/lite/src/runtime/kernel/arm/fp32/gelu_fp32.h diff --git a/mindspore/lite/nnacl/fp32/gelu_fp32.c b/mindspore/lite/nnacl/fp32/gelu_fp32.c new file mode 100644 index 0000000000..8eee72cc9e --- /dev/null +++ b/mindspore/lite/nnacl/fp32/gelu_fp32.c @@ -0,0 +1,39 @@ +/** + * Copyright 2019 Huawei Technologies Co., Ltd + * + * 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. + */ + +#include "nnacl/fp32/gelu_fp32.h" +#include "nnacl/gelu_parameter.h" +#include +#include +#include "nnacl/errorcode.h" + +int DoGeLU(float *src, float *out, int64_t real_dst_count, const GeLUParameter *param) { + if (src == NULL || out == NULL) { + return NNACL_ERR; + } + + if (param->approximate_) { + for (int i = 0; i < real_dst_count; i++) { + out[i] = 0.5 * src[i] * (1.0 + tanh(0.7978845608028654 * (src[i] + 0.044715 * pow(src[i], 3)))); + } + } else { + for (int i = 0; i < real_dst_count; i++) { + out[i] = 0.5 * src[i] * (1.0 + erf(src[i] / 1.4142135623730951)); + } + } + + return NNACL_OK; +} diff --git a/mindspore/lite/nnacl/fp32/gelu_fp32.h b/mindspore/lite/nnacl/fp32/gelu_fp32.h new file mode 100644 index 0000000000..9a23619635 --- /dev/null +++ b/mindspore/lite/nnacl/fp32/gelu_fp32.h @@ -0,0 +1,31 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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 MINDSPORE_LITE_NNACL_FP32_GELU_H_ +#define MINDSPORE_LITE_NNACL_FP32_GELU_H_ + +#include "nnacl/op_base.h" +#include "nnacl/gelu_parameter.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int DoGeLU(float *src, float *out, int64_t real_dst_count, const GeLUParameter *param); +#ifdef __cplusplus +} +#endif + +#endif // MINDSPORE_LITE_NNACL_FP32_GELU_H_ diff --git a/mindspore/lite/nnacl/gelu_parameter.h b/mindspore/lite/nnacl/gelu_parameter.h new file mode 100644 index 0000000000..7a16900665 --- /dev/null +++ b/mindspore/lite/nnacl/gelu_parameter.h @@ -0,0 +1,28 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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 MINDSPORE_LITE_NNACL_GELU_PARAMETER_H_ +#define MINDSPORE_LITE_NNACL_GELU_PARAMETER_H_ + +#include "nnacl/op_base.h" + +typedef struct GeLUParameter { + // Primitive parameter + OpParameter op_parameter_; + bool approximate_; +} GeLUParameter; + +#endif // MINDSPORE_LITE_NNACL_GELU_PARAMETER_H_ diff --git a/mindspore/lite/schema/ops.fbs b/mindspore/lite/schema/ops.fbs index 4b292964f2..942d75ce3e 100644 --- a/mindspore/lite/schema/ops.fbs +++ b/mindspore/lite/schema/ops.fbs @@ -1226,3 +1226,7 @@ table Reciprocal { table Merge { } + +table GeLU { + approximate : bool = false; +} diff --git a/mindspore/lite/src/ops/gelu.cc b/mindspore/lite/src/ops/gelu.cc new file mode 100644 index 0000000000..14e9fdfc3d --- /dev/null +++ b/mindspore/lite/src/ops/gelu.cc @@ -0,0 +1,42 @@ +/** + * Copyright 2019-2020 Huawei Technologies Co., Ltd + * + * 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. + */ + +#include "src/ops/gelu.h" +#include +#include "include/errorcode.h" +#include "src/common/log_adapter.h" +#include "src/tensor.h" +#ifndef PRIMITIVE_WRITEABLE +#include "src/ops/ops_register.h" +#endif + +namespace mindspore { +namespace lite { +#ifdef PRIMITIVE_WRITEABLE +// int GeLU::GetApproximate() const { return this->primitive_->value.AsGeLU()->approximate; } + +// void GeLU::SetApproximate(bool approximate) { this->primitive_->value.AsGeLU()->approximate = approximate; } + +#else +// int GeLU::GetApproximate() const { return this->primitive_->value_as_GeLU()->approximate(); } + +// PrimitiveC *GeLUCreator(const schema::Primitive *primitive) { return PrimitiveC::NewPrimitiveC(primitive); } +// Registry GeLURegistry(schema::PrimitiveType_GeLU, GeLUCreator); + +#endif + +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/ops/gelu.h b/mindspore/lite/src/ops/gelu.h new file mode 100644 index 0000000000..27721fc744 --- /dev/null +++ b/mindspore/lite/src/ops/gelu.h @@ -0,0 +1,45 @@ +/** + * Copyright 2019-2020 Huawei Technologies Co., Ltd + * + * 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 LITE_MINDSPORE_LITE_C_OPS_GELU_H_ +#define LITE_MINDSPORE_LITE_C_OPS_GELU_H_ + +#include +#include +#include +#include "src/ops/primitive_c.h" + +namespace mindspore { +namespace lite { +class GeLU : public PrimitiveC { + public: + GeLU() = default; + ~GeLU() = default; +#ifdef PRIMITIVE_WRITEABLE + MS_DECLARE_PARENT(GeLU, PrimitiveC); + explicit GeLU(schema::PrimitiveT *primitive) : PrimitiveC(primitive) {} +// int UnPackAttr(const Primitive &prim, const std::vector &inputs) override; +// void SetApproximate(bool approximate); +#else +// int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; +#endif + int InferShape(std::vector inputs_, std::vector outputs_) override; + // bool GetApproximate() const; +}; +} // namespace lite +} // namespace mindspore + +#endif // LITE_MINDSPORE_LITE_C_OPS_GELU_H_ diff --git a/mindspore/lite/src/ops/populate/gelu_populate.cc b/mindspore/lite/src/ops/populate/gelu_populate.cc new file mode 100644 index 0000000000..320a231884 --- /dev/null +++ b/mindspore/lite/src/ops/populate/gelu_populate.cc @@ -0,0 +1,40 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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. + */ + +#include "src/ops/primitive_c.h" +#include "src/ops/populate/populate_register.h" +#include "src/ops/gelu.h" +#include "nnacl/gelu_parameter.h" + +namespace mindspore { +namespace lite { +OpParameter *PopulateGeLUParameter(const mindspore::lite::PrimitiveC *primitive) { + // const auto param = reinterpret_cast(const_cast(primitive)); + GeLUParameter *gelu_param = reinterpret_cast(malloc(sizeof(GeLUParameter))); + if (gelu_param == nullptr) { + MS_LOG(ERROR) << "malloc GeLUParameter failed."; + return nullptr; + } + memset(gelu_param, 0, sizeof(GeLUParameter)); + gelu_param->op_parameter_.type_ = primitive->Type(); + // gelu_param->approximate_ = param->GetApproximate(); + return reinterpret_cast(gelu_param); +} + +// Registry GeLUParameterRegistry(schema::PrimitiveType_GeLU, PopulateGeLUParameter); +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/runtime/kernel/arm/base/gelu_base.cc b/mindspore/lite/src/runtime/kernel/arm/base/gelu_base.cc new file mode 100644 index 0000000000..cbdddfa02c --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/base/gelu_base.cc @@ -0,0 +1,59 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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. + */ +#include "src/runtime/kernel/arm/base/gelu_base.h" +#include +#include "src/runtime/kernel/arm/fp32/gelu_fp32.h" +#include "nnacl/fp32/gelu_fp32.h" +#include "schema/model_generated.h" +#include "src/kernel_registry.h" +#include "include/errorcode.h" +#include "include/context.h" + +using mindspore::lite::KernelRegistrar; +using mindspore::lite::RET_ERROR; +using mindspore::lite::RET_OK; +// using mindspore::schema::PrimitiveType_GeLU; + +namespace mindspore::kernel { +int GeLUBaseCPUKernel::Init() { return RET_OK; } + +kernel::LiteKernel *CpuGeLUFp32KernelCreator(const std::vector &inputs, + const std::vector &outputs, OpParameter *opParameter, + const InnerContext *ctx, const kernel::KernelKey &desc, + const mindspore::lite::PrimitiveC *primitive) { + if (opParameter == nullptr) { + MS_LOG(ERROR) << "Input opParameter is nullptr!"; + return nullptr; + } + // MS_ASSERT(desc.type == schema::PrimitiveType_GeLU); + auto *kernel = new (std::nothrow) GeLUCPUKernel(opParameter, inputs, outputs, ctx, primitive); + if (kernel == nullptr) { + MS_LOG(ERROR) << "new GeLUCPUKernel fail!"; + free(opParameter); + return nullptr; + } + auto ret = kernel->Init(); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " + << schema::EnumNamePrimitiveType(static_cast(opParameter->type_)); + delete kernel; + return nullptr; + } + return kernel; +} + +// REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_GeLU, CpuGeLUFp32KernelCreator) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/base/gelu_base.h b/mindspore/lite/src/runtime/kernel/arm/base/gelu_base.h new file mode 100644 index 0000000000..49d5459483 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/base/gelu_base.h @@ -0,0 +1,50 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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 MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_BASE_GELU_BASE_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_BASE_GELU_BASE_H_ + +#include +#include "src/lite_kernel.h" +#include "nnacl/gelu_parameter.h" +#include "src/runtime/kernel/arm/base/layout_transform.h" + +using mindspore::lite::InnerContext; + +namespace mindspore::kernel { +class GeLUBaseCPUKernel : public LiteKernel { + public: + GeLUBaseCPUKernel(OpParameter *parameter, const std::vector &inputs, + const std::vector &outputs, const InnerContext *ctx, + const mindspore::lite::PrimitiveC *primitive) + : LiteKernel(parameter, inputs, outputs, ctx, primitive), ctx_(ctx), thread_count_(ctx->thread_num_) { + gelu_param_ = reinterpret_cast(op_parameter_); + } + + virtual ~GeLUBaseCPUKernel() = default; + + int Init() override; + + int Run() override { return 0; } + + protected: + const InnerContext *ctx_ = nullptr; + int thread_count_ = 1; + GeLUParameter *gelu_param_ = nullptr; +}; +} // namespace mindspore::kernel + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_BASE_GELU_BASE_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/gelu_fp32.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/gelu_fp32.cc new file mode 100644 index 0000000000..13834357d8 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/gelu_fp32.cc @@ -0,0 +1,88 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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. + */ + +#include "src/runtime/kernel/arm/fp32/gelu_fp32.h" +#include "src/runtime/kernel/arm/base/gelu_base.h" +#include "nnacl/fp32/gelu_fp32.h" +#include "nnacl/gelu_parameter.h" +#include "src/kernel_registry.h" +#include "include/errorcode.h" +#include "src/runtime/runtime_api.h" + +using mindspore::kernel::KERNEL_ARCH::kCPU; +using mindspore::lite::KernelRegistrar; +using mindspore::lite::RET_ERROR; +using mindspore::lite::RET_OK; +// using mindspore::schema::PrimitiveType_GeLU; + +namespace mindspore::kernel { + +int GeLUCPUKernel::Init() { + auto ret = GeLUBaseCPUKernel::Init(); + if (ret != RET_OK) { + return ret; + } + + if (!InferShapeDone()) { + return RET_OK; + } + + return ReSize(); +} + +int GeLUCPUKernel::ReSize() { return RET_OK; } + +int GeLUCPUKernel::GeLU(int task_id) { + int64_t real_dst_count = MSMIN(elements_num_ - task_id * count_unit_, count_unit_); + if (real_dst_count <= 0) { + return lite::RET_OK; + } + float *cur_input_data = input_ptr_ + task_id * count_unit_; + float *cur_output_data = output_ptr_ + task_id * count_unit_; + auto ret = DoGeLU(cur_input_data, cur_output_data, real_dst_count, gelu_param_); + if (ret != RET_OK) { + MS_LOG(ERROR) << "GeLU error task_id[" << task_id << "] error_code[" << ret << "]"; + return RET_ERROR; + } + return RET_OK; +} + +int GeLURun(void *cdata, int task_id) { + auto g_kernel = reinterpret_cast(cdata); + auto ret = g_kernel->GeLU(task_id); + if (ret != RET_OK) { + MS_LOG(ERROR) << "GeLURun error task_id[" << task_id << "] error_code[" << ret << "]"; + return RET_ERROR; + } + return RET_OK; +} + +int GeLUCPUKernel::Run() { + auto in_tensor = in_tensors_.front(); + auto out_tensor = out_tensors_.front(); + input_ptr_ = reinterpret_cast(in_tensor->MutableData()); + output_ptr_ = reinterpret_cast(out_tensor->MutableData()); + elements_num_ = out_tensor->ElementsNum(); + count_unit_ = thread_count_ > 1 ? UP_DIV(elements_num_, thread_count_) : elements_num_; + auto ret = ParallelLaunch(this->context_->thread_pool_, GeLURun, this, thread_count_); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Scale error error_code[" << ret << "]"; + return RET_ERROR; + } + + return RET_OK; +} +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/gelu_fp32.h b/mindspore/lite/src/runtime/kernel/arm/fp32/gelu_fp32.h new file mode 100644 index 0000000000..d88d0aad5f --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/gelu_fp32.h @@ -0,0 +1,46 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * 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 MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GELU_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GELU_H_ + +#include +#include "src/runtime/kernel/arm/base/gelu_base.h" +#include "src/lite_kernel.h" + +namespace mindspore::kernel { +class GeLUCPUKernel : public GeLUBaseCPUKernel { + public: + GeLUCPUKernel(OpParameter *parameter, const std::vector &inputs, + const std::vector &outputs, const lite::InnerContext *ctx, + const mindspore::lite::PrimitiveC *primitive) + : GeLUBaseCPUKernel(parameter, inputs, outputs, ctx, primitive) {} + ~GeLUCPUKernel() override = default; + + int Init() override; + int ReSize() override; + int Run() override; + int GeLU(int task_id); + + private: + float *input_ptr_ = nullptr; + float *output_ptr_ = nullptr; + int64_t elements_num_ = 0; + int64_t count_unit_ = 0; +}; +} // namespace mindspore::kernel + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GELU_H_