From e8df3226512c4c152f33e4784c0ad1d501976ea1 Mon Sep 17 00:00:00 2001 From: zyfncg Date: Tue, 10 Aug 2021 17:50:36 +0800 Subject: [PATCH] Support npu op fill_any_like (#34518) * Support npu kernel for fill_any_like op * modify the description of exception * remove useless template element * remove useless decorator * fix the code format error --- paddle/fluid/operators/fill_any_like_op.h | 17 ++-- .../fluid/operators/fill_any_like_op_npu.cc | 79 +++++++++++++++++ .../npu/test_fill_any_like_op_npu.py | 88 +++++++++++++++++++ 3 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 paddle/fluid/operators/fill_any_like_op_npu.cc create mode 100644 python/paddle/fluid/tests/unittests/npu/test_fill_any_like_op_npu.py diff --git a/paddle/fluid/operators/fill_any_like_op.h b/paddle/fluid/operators/fill_any_like_op.h index 9c514ed3aaa..2fb7bf985f2 100644 --- a/paddle/fluid/operators/fill_any_like_op.h +++ b/paddle/fluid/operators/fill_any_like_op.h @@ -45,15 +45,18 @@ class FillAnyLikeKernel : public framework::OpKernel { static_cast(std::numeric_limits::lowest())) && (common_type_value <= static_cast(std::numeric_limits::max())), - true, platform::errors::InvalidArgument( - "filled value is out of range for" - " targeted type in fill_any_like, your kernel type is %s" - ", please check value you set.", - typeid(T).name())); + true, + platform::errors::InvalidArgument( + "The filled value is out of range for target type, " + "current kernel type is %s, the range should between %f " + "and %f, but now value is %f.", + typeid(T).name(), + static_cast(std::numeric_limits::lowest()), + static_cast(std::numeric_limits::max()), value)); + PADDLE_ENFORCE_EQ( std::isnan(value), false, - platform::errors::InvalidArgument("filled value should not be NaN," - " but received NaN")); + platform::errors::InvalidArgument("The filled value is NaN.")); math::SetConstant setter; setter(context.template device_context(), out, diff --git a/paddle/fluid/operators/fill_any_like_op_npu.cc b/paddle/fluid/operators/fill_any_like_op_npu.cc new file mode 100644 index 00000000000..d5204f5cacf --- /dev/null +++ b/paddle/fluid/operators/fill_any_like_op_npu.cc @@ -0,0 +1,79 @@ +/* Copyright (c) 2021 PaddlePaddle Authors. 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. */ + +#include "paddle/fluid/operators/fill_any_like_op.h" +#include "paddle/fluid/operators/npu_op_runner.h" + +namespace paddle { +namespace operators { + +template +class FillAnyLikeNPUKernel : public framework::OpKernel { + public: + using CommonType = typename std::common_type< + float, + typename std::conditional::value, + float, T>::type>::type; + + void Compute(const framework::ExecutionContext& context) const override { + auto data_type = static_cast( + context.Attr("dtype")); + auto* out = context.Output("Out"); + out->mutable_data(context.GetPlace()); + + float value = context.Attr("value"); + + auto common_type_value = static_cast(value); + + PADDLE_ENFORCE_EQ( + (common_type_value >= + static_cast(std::numeric_limits::lowest())) && + (common_type_value <= + static_cast(std::numeric_limits::max())), + true, + platform::errors::InvalidArgument( + "The filled value is out of range for target type, " + "current kernel type is %s, the range should between %f " + "and %f, but now value is %f.", + typeid(T).name(), + static_cast(std::numeric_limits::lowest()), + static_cast(std::numeric_limits::max()), value)); + + PADDLE_ENFORCE_EQ( + std::isnan(value), false, + platform::errors::InvalidArgument("The filled value is NaN.")); + + Tensor tensor_tmp(data_type); + tensor_tmp.mutable_data({1}, context.GetPlace()); + FillNpuTensorWithConstant(&tensor_tmp, static_cast(value)); + + auto stream = + context.template device_context() + .stream(); + + auto shape = out->dims(); + const auto& runner = NpuOpRunner("FillD", {tensor_tmp}, {*out}, + {{"dims", framework::vectorize(shape)}}); + runner.Run(stream); + } +}; + +} // namespace operators +} // namespace paddle + +namespace ops = paddle::operators; + +REGISTER_OP_NPU_KERNEL(fill_any_like, ops::FillAnyLikeNPUKernel, + ops::FillAnyLikeNPUKernel, + ops::FillAnyLikeNPUKernel); diff --git a/python/paddle/fluid/tests/unittests/npu/test_fill_any_like_op_npu.py b/python/paddle/fluid/tests/unittests/npu/test_fill_any_like_op_npu.py new file mode 100644 index 00000000000..a687509e6ae --- /dev/null +++ b/python/paddle/fluid/tests/unittests/npu/test_fill_any_like_op_npu.py @@ -0,0 +1,88 @@ +# Copyright (c) 2021 PaddlePaddle Authors. 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. + +from __future__ import print_function + +import numpy as np +import unittest +import sys +sys.path.append("..") +from op_test import OpTest +import paddle +import paddle.fluid as fluid +from paddle.fluid import core + +paddle.enable_static() + + +class TestFillAnyLikeNPUOp(OpTest): + def setUp(self): + self.set_npu() + self.place = paddle.NPUPlace(0) + self.op_type = "fill_any_like" + self.dtype = np.float32 + self.shape = [2, 3, 4, 5] + self.value = 0.0 + + self.init() + + self.inputs = {'X': np.random.random(self.shape).astype(self.dtype)} + self.attrs = {'value': self.value} + self.outputs = {'Out': np.full(self.shape, self.value, self.dtype)} + + def init(self): + pass + + def set_npu(self): + self.__class__.use_npu = True + + def test_check_output(self): + self.check_output_with_place(self.place) + + +class TestFillAnyLikeNPUOpInt32(TestFillAnyLikeNPUOp): + def init(self): + self.dtype = np.int32 + self.value = -1 + + +class TestFillAnyLikeNPUOpFloat32(TestFillAnyLikeNPUOp): + def init(self): + self.dtype = np.float32 + self.value = 0.09 + + +class TestFillAnyLikeNPUOpFloat16(TestFillAnyLikeNPUOp): + def init(self): + self.dtype = np.float16 + self.value = 0.05 + + +class TestFillAnyLikeNPUOpValue1(TestFillAnyLikeNPUOp): + def init(self): + self.value = 1.0 + + +class TestFillAnyLikeNPUOpValue2(TestFillAnyLikeNPUOp): + def init(self): + self.value = 1e-9 + + +class TestFillAnyLikeNPUOpShape(TestFillAnyLikeNPUOp): + def init(self): + self.shape = [12, 10] + + +if __name__ == "__main__": + unittest.main() -- GitLab