From 450109eefb4ef63e36379a42ab61a9655cfeab65 Mon Sep 17 00:00:00 2001 From: x00540480 Date: Tue, 8 Dec 2020 16:00:48 +0800 Subject: [PATCH] expm1 operator --- .../kernel_compiler/cpu/expm1_cpu_kernel.cc | 66 +++++++++++++++++++ .../kernel_compiler/cpu/expm1_cpu_kernel.h | 53 +++++++++++++++ mindspore/ops/operations/math_ops.py | 2 +- tests/st/ops/cpu/test_expm1_op.py | 53 +++++++++++++++ 4 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 mindspore/ccsrc/backend/kernel_compiler/cpu/expm1_cpu_kernel.cc create mode 100644 mindspore/ccsrc/backend/kernel_compiler/cpu/expm1_cpu_kernel.h create mode 100644 tests/st/ops/cpu/test_expm1_op.py diff --git a/mindspore/ccsrc/backend/kernel_compiler/cpu/expm1_cpu_kernel.cc b/mindspore/ccsrc/backend/kernel_compiler/cpu/expm1_cpu_kernel.cc new file mode 100644 index 0000000000..02f7433599 --- /dev/null +++ b/mindspore/ccsrc/backend/kernel_compiler/cpu/expm1_cpu_kernel.cc @@ -0,0 +1,66 @@ +/** + * 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 "backend/kernel_compiler/cpu/expm1_cpu_kernel.h" +#include +#include "runtime/device/cpu/cpu_device_address.h" + +namespace mindspore { +namespace kernel { +void Expm1CPUKernel::InitKernel(const CNodePtr &kernel_node) { + MS_EXCEPTION_IF_NULL(kernel_node); + size_t input_num = AnfAlgo::GetInputTensorNum(kernel_node); + if (input_num != 1) { + MS_LOG(EXCEPTION) << "Input number is " << input_num << ", but Expm1CPUKernel needs 1 inputs."; + } + size_t output_num = AnfAlgo::GetOutputTensorNum(kernel_node); + if (output_num != 1) { + MS_LOG(EXCEPTION) << "Output number is " << output_num << ", but Expm1CPUKernel needs 1 output."; + } + + input_dtype_ = AnfAlgo::GetPrevNodeOutputInferDataType(kernel_node, 0); + if (input_dtype_ != kNumberTypeFloat16 && input_dtype_ != kNumberTypeFloat32 && input_dtype_ != kNumberTypeFloat) { + MS_LOG(EXCEPTION) << "Unsupported input type found."; + } +} + +bool Expm1CPUKernel::Launch(const std::vector &inputs, + const std::vector & /*workspace*/, + const std::vector &outputs) { + if (input_dtype_ == kNumberTypeFloat16) { + LaunchKernel(inputs, outputs); + } else if (input_dtype_ == kNumberTypeFloat32 || input_dtype_ == kNumberTypeFloat) { + LaunchKernel(inputs, outputs); + } else { + MS_LOG(EXCEPTION) << "Only support float, half, but actual data type is " << TypeIdLabel(input_dtype_); + } + return true; +} + +template +void Expm1CPUKernel::LaunchKernel(const std::vector &inputs, + const std::vector &outputs) { + T *input = reinterpret_cast(inputs[0]->addr); + T *output = reinterpret_cast(outputs[0]->addr); + + size_t elem_num = inputs[0]->size / sizeof(T); + + for (size_t i = 0; i < elem_num; i++) { + output[i] = exp(input[i]) - T(1); + } +} +} // namespace kernel +} // namespace mindspore diff --git a/mindspore/ccsrc/backend/kernel_compiler/cpu/expm1_cpu_kernel.h b/mindspore/ccsrc/backend/kernel_compiler/cpu/expm1_cpu_kernel.h new file mode 100644 index 0000000000..d918a2cb7a --- /dev/null +++ b/mindspore/ccsrc/backend/kernel_compiler/cpu/expm1_cpu_kernel.h @@ -0,0 +1,53 @@ +/** + * 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_CCSRC_BACKEND_KERNEL_COMPILER_CPU_EXPM1_CPU_KERNEL_H_ +#define MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_EXPM1_CPU_KERNEL_H_ + +#include +#include "backend/kernel_compiler/cpu/cpu_kernel.h" +#include "backend/kernel_compiler/cpu/cpu_kernel_factory.h" + +namespace mindspore { +namespace kernel { +class Expm1CPUKernel : public CPUKernel { + public: + Expm1CPUKernel() = default; + ~Expm1CPUKernel() override = default; + + void InitKernel(const CNodePtr &kernelNode) override; + + bool Launch(const std::vector &inputs, const std::vector &workspace, + const std::vector &outputs) override; + + private: + template + void LaunchKernel(const std::vector &inputs, const std::vector &outputs); + + private: + TypeId input_dtype_{kTypeUnknown}; +}; + +MS_REG_CPU_KERNEL(Expm1, KernelAttr().AddInputAttr(kNumberTypeFloat16).AddOutputAttr(kNumberTypeFloat16), + Expm1CPUKernel); + +MS_REG_CPU_KERNEL(Expm1, KernelAttr().AddInputAttr(kNumberTypeFloat32).AddOutputAttr(kNumberTypeFloat32), + Expm1CPUKernel); + +MS_REG_CPU_KERNEL(Expm1, KernelAttr().AddInputAttr(kNumberTypeFloat).AddOutputAttr(kNumberTypeFloat32), Expm1CPUKernel); +} // namespace kernel +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_EXPM1_CPU_KERNEL_H_ diff --git a/mindspore/ops/operations/math_ops.py b/mindspore/ops/operations/math_ops.py index 54d19c10e4..7409421fb9 100644 --- a/mindspore/ops/operations/math_ops.py +++ b/mindspore/ops/operations/math_ops.py @@ -1588,7 +1588,7 @@ class Expm1(PrimitiveWithInfer): Tensor, has the same shape as the `input_x`. Supported Platforms: - ``Ascend`` + ``Ascend`` ``GPU`` ``CPU`` Examples: >>> input_x = Tensor(np.array([0.0, 1.0, 2.0, 4.0]), mindspore.float32) diff --git a/tests/st/ops/cpu/test_expm1_op.py b/tests/st/ops/cpu/test_expm1_op.py new file mode 100644 index 0000000000..a930ddccc6 --- /dev/null +++ b/tests/st/ops/cpu/test_expm1_op.py @@ -0,0 +1,53 @@ +# 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. +# ============================================================================ + +import numpy as np +import pytest + +import mindspore.context as context +import mindspore.nn as nn +from mindspore import Tensor +from mindspore.ops import operations as P +from mindspore import dtype + +context.set_context(mode=context.GRAPH_MODE, device_target="CPU") + + +class NetExpm1(nn.Cell): + def __init__(self): + super(NetExpm1, self).__init__() + self.expm1 = P.Expm1() + + def construct(self, x): + return self.expm1(x) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_cpu +@pytest.mark.env_onecard +def test_expm1_op(): + x = np.random.rand(3, 8).astype(np.float32) + y = np.random.rand(3, 8).astype(np.float16) + + expm1 = NetExpm1() + output_x = expm1(Tensor(x, dtype=dtype.float32)) + expect_x = np.expm1(x) + tol_x = 1e-6 + assert (np.abs(output_x.asnumpy() - expect_x) < tol_x).all() + + output_y = expm1(Tensor(y, dtype=dtype.float16)) + expect_y = np.expm1(y) + tol_y = 1e-3 + assert (np.abs(output_y.asnumpy() - expect_y) < tol_y).all()