From 9fb7dff3a25757abc276f874f8d45fa62b6af542 Mon Sep 17 00:00:00 2001 From: Aurelius84 Date: Mon, 11 Apr 2022 13:44:58 +0800 Subject: [PATCH] [Eager]Fix segment_pool/allclose/isclose/scale API bug (#41506) (#41554) * [Eager]Fix segment_pool/allclose/isclose/scale API bug (#41506) * [Eager]Fix segment_pool/allclose/isclose/scale API bug * fix kernel register problem * add norm, segment_pool (#41465) Co-authored-by: hong <43953930+phlrain@users.noreply.github.com> --- paddle/fluid/operators/cast_op.cu | 22 +++++++++---------- .../fluid/tests/unittests/test_bincount_op.py | 5 ++++- .../fluid/tests/unittests/test_norm_op.py | 1 + .../fluid/tests/unittests/test_segment_ops.py | 18 +++++++++++++-- python/paddle/incubate/tensor/math.py | 8 +++---- python/paddle/tensor/linalg.py | 7 ++---- python/paddle/tensor/logic.py | 14 ++++++++++-- python/paddle/utils/code_gen/api.yaml | 11 ++++++++++ python/paddle/utils/code_gen/backward.yaml | 14 +++++++++++- 9 files changed, 74 insertions(+), 26 deletions(-) diff --git a/paddle/fluid/operators/cast_op.cu b/paddle/fluid/operators/cast_op.cu index eb51215790b..0afe09ec028 100644 --- a/paddle/fluid/operators/cast_op.cu +++ b/paddle/fluid/operators/cast_op.cu @@ -19,15 +19,15 @@ namespace ops = paddle::operators; namespace plat = paddle::platform; using CUDA = paddle::platform::CUDADeviceContext; -#define REGISTER_CAST_CUDA_BASE(op_name, ...) \ - REGISTER_OP_CUDA_KERNEL( \ - op_name, ops::CastOpKernel, \ - ops::CastOpKernel, ops::CastOpKernel, \ - ops::CastOpKernel, ops::CastOpKernel, \ - ops::CastOpKernel, ops::CastOpKernel, \ - ops::CastOpKernel, \ - ops::CastOpKernel>, \ - ops::CastOpKernel>, ##__VA_ARGS__); - // See [ why register transfer_dtype_op alias with cast_op? ] in cast_op.cc -REGISTER_CAST_CUDA_BASE(transfer_dtype, ops::CastOpKernel) +REGISTER_OP_CUDA_KERNEL(transfer_dtype, ops::CastOpKernel, + ops::CastOpKernel, + ops::CastOpKernel, + ops::CastOpKernel, + ops::CastOpKernel, + ops::CastOpKernel, + ops::CastOpKernel, + ops::CastOpKernel, + ops::CastOpKernel>, + ops::CastOpKernel>, + ops::CastOpKernel); diff --git a/python/paddle/fluid/tests/unittests/test_bincount_op.py b/python/paddle/fluid/tests/unittests/test_bincount_op.py index 851bf7b0112..17b04b954af 100644 --- a/python/paddle/fluid/tests/unittests/test_bincount_op.py +++ b/python/paddle/fluid/tests/unittests/test_bincount_op.py @@ -126,6 +126,7 @@ class TestBincountOp(OpTest): # without weights def setUp(self): self.op_type = "bincount" + self.python_api = paddle.bincount self.init_test_case() self.inputs = {"X": self.np_input} self.attrs = {"minlength": self.minlength} @@ -137,13 +138,14 @@ class TestBincountOp(OpTest): self.Out = np.bincount(self.np_input, minlength=self.minlength) def test_check_output(self): - self.check_output() + self.check_output(check_eager=False) class TestCase1(TestBincountOp): # with weights(FLOAT32) def setUp(self): self.op_type = "bincount" + self.python_api = paddle.bincount self.init_test_case() self.inputs = {"X": self.np_input, "Weights": self.np_weights} self.attrs = {"minlength": self.minlength} @@ -163,6 +165,7 @@ class TestCase2(TestBincountOp): # with weights(other) def setUp(self): self.op_type = "bincount" + self.python_api = paddle.bincount self.init_test_case() self.inputs = {"X": self.np_input, "Weights": self.np_weights} self.attrs = {"minlength": self.minlength} diff --git a/python/paddle/fluid/tests/unittests/test_norm_op.py b/python/paddle/fluid/tests/unittests/test_norm_op.py index 626de9b12b9..49e1f253349 100644 --- a/python/paddle/fluid/tests/unittests/test_norm_op.py +++ b/python/paddle/fluid/tests/unittests/test_norm_op.py @@ -32,6 +32,7 @@ def l2_norm(x, axis, epsilon): class TestNormOp(OpTest): def setUp(self): self.op_type = "norm" + self.python_api = paddle.fluid.layers.l2_normalize self.init_test_case() self.init_dtype() x = np.random.random(self.shape).astype(self.dtype) diff --git a/python/paddle/fluid/tests/unittests/test_segment_ops.py b/python/paddle/fluid/tests/unittests/test_segment_ops.py index e2aadbedbd0..90d597837a8 100644 --- a/python/paddle/fluid/tests/unittests/test_segment_ops.py +++ b/python/paddle/fluid/tests/unittests/test_segment_ops.py @@ -73,6 +73,17 @@ def compute_segment_min_max(x, segment_ids, pooltype="MAX"): return results, gradient / results.size +def segment_pool_split(X, SegmentIds, pooltype): + if pooltype == "SUM": + return paddle.incubate.tensor.segment_sum(X, SegmentIds) + elif pooltype == "MEAN": + return paddle.incubate.tensor.segment_mean(X, SegmentIds) + elif pooltype == "MIN": + return paddle.incubate.tensor.segment_min(X, SegmentIds) + elif pooltype == "MAX": + return paddle.incubate.tensor.segment_max(X, SegmentIds) + + class TestSegmentOps(OpTest): def set_data(self): x = np.random.uniform(-1, 1, self.shape).astype(self.dtype) @@ -90,6 +101,8 @@ class TestSegmentOps(OpTest): def prepare(self): self.op_type = "segment_pool" + self.python_api = segment_pool_split + self.python_out_sig = ["Out"] self.dtype = np.float64 self.shape = [30, 15] self.attrs = {"pooltype": "SUM"} @@ -105,10 +118,10 @@ class TestSegmentOps(OpTest): self.outputs = {'Out': result.astype(self.dtype)} def test_check_output(self): - self.check_output() + self.check_output(check_eager=True) def test_check_grad(self): - self.check_grad(["X"], "Out") + self.check_grad(["X"], "Out", check_eager=True) class TestSegmentSum2(TestSegmentOps): @@ -259,4 +272,5 @@ class API_SegmentOpsTest(unittest.TestCase): if __name__ == '__main__': + paddle.enable_static() unittest.main() diff --git a/python/paddle/incubate/tensor/math.py b/python/paddle/incubate/tensor/math.py index b36aaef9acf..07dc7c1581f 100644 --- a/python/paddle/incubate/tensor/math.py +++ b/python/paddle/incubate/tensor/math.py @@ -52,7 +52,7 @@ def segment_sum(data, segment_ids, name=None): """ if in_dygraph_mode(): - return _C_ops.final_state_segment_pool(data, segment_idsm, "SUM")[0] + return _C_ops.final_state_segment_pool(data, segment_ids, "SUM")[0] if _in_legacy_dygraph(): out, tmp = _C_ops.segment_pool(data, segment_ids, 'pooltype', "SUM") return out @@ -109,7 +109,7 @@ def segment_mean(data, segment_ids, name=None): """ if in_dygraph_mode(): - return _C_ops.final_state_segment_pool(data, segment_idsm, "MEAN")[0] + return _C_ops.final_state_segment_pool(data, segment_ids, "MEAN")[0] if _non_static_mode(): out, tmp = _C_ops.segment_pool(data, segment_ids, 'pooltype', "MEAN") return out @@ -165,7 +165,7 @@ def segment_min(data, segment_ids, name=None): """ if in_dygraph_mode(): - return _C_ops.final_state_segment_pool(data, segment_idsm, "MIN")[0] + return _C_ops.final_state_segment_pool(data, segment_ids, "MIN")[0] if _non_static_mode(): out, tmp = _C_ops.segment_pool(data, segment_ids, 'pooltype', "MIN") @@ -222,7 +222,7 @@ def segment_max(data, segment_ids, name=None): """ if in_dygraph_mode(): - out, tmp = _C_ops.final_state_segment_pool(data, segment_ids, "MAX")[0] + out, tmp = _C_ops.final_state_segment_pool(data, segment_ids, "MAX") return out if _non_static_mode(): diff --git a/python/paddle/tensor/linalg.py b/python/paddle/tensor/linalg.py index c4814bd2b2f..07a7b503d3b 100644 --- a/python/paddle/tensor/linalg.py +++ b/python/paddle/tensor/linalg.py @@ -17,7 +17,7 @@ from ..fluid.layer_helper import LayerHelper from ..framework import _varbase_creator, _dygraph_tracer from ..fluid.data_feeder import check_variable_and_dtype, check_type, check_dtype from ..static import Variable -from ..fluid.framework import _in_legacy_dygraph, in_dygraph_mode +from ..fluid.framework import _in_legacy_dygraph, in_dygraph_mode, _non_static_mode from ..fluid.layers import transpose, cast # noqa: F401 from ..fluid import layers import paddle @@ -1466,10 +1466,7 @@ def bincount(x, weights=None, minlength=0, name=None): if x.dtype not in [paddle.int32, paddle.int64]: raise TypeError("Elements in Input(x) should all be integers") - # if in_dygraph_mode(): - # return _C_ops.final_state_bincount(x, weights, minlength) - - if _in_legacy_dygraph(): + if _non_static_mode(): return _C_ops.bincount(x, weights, "minlength", minlength) helper = LayerHelper('bincount', **locals()) diff --git a/python/paddle/tensor/logic.py b/python/paddle/tensor/logic.py index 03d0f42d841..972a2f72968 100755 --- a/python/paddle/tensor/logic.py +++ b/python/paddle/tensor/logic.py @@ -123,7 +123,12 @@ def allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name=None): """ if in_dygraph_mode(): - return _C_ops.final_state_allclose(x, y, rtol, atol, equal_nan) + # NOTE(dev): Pass tol as Tensor to fix precision loss problem, because + # C++ backend will cast it into float32 if passing float from python. + as_tensor = lambda x: paddle.to_tensor([x], dtype='float64', place='cpu') + return _C_ops.final_state_allclose(x, y, + as_tensor(rtol), + as_tensor(atol), equal_nan) if _in_legacy_dygraph(): return _C_ops.allclose(x, y, 'rtol', str(rtol), 'atol', @@ -685,7 +690,12 @@ def isclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name=None): """ if in_dygraph_mode(): - return _C_ops.final_state_isclose(x, y, rtol, atol, equal_nan) + # NOTE(dev): Pass tol as Tensor to fix precision loss problem, because + # C++ backend will cast it into float32 if passing float from python. + as_tensor = lambda x: paddle.to_tensor([x], dtype='float64', place='cpu') + return _C_ops.final_state_isclose(x, y, + as_tensor(rtol), + as_tensor(atol), equal_nan) if _in_legacy_dygraph(): return _C_ops.isclose(x, y, 'rtol', str(rtol), 'atol', diff --git a/python/paddle/utils/code_gen/api.yaml b/python/paddle/utils/code_gen/api.yaml index fa5706836d8..97b8cd7c918 100644 --- a/python/paddle/utils/code_gen/api.yaml +++ b/python/paddle/utils/code_gen/api.yaml @@ -1252,6 +1252,16 @@ optional : weight backward : nll_loss_grad +- api : norm + args : (Tensor x, int axis, float epsilon, bool is_test) + output : Tensor(out), Tensor(norm) + infer_meta : + func : NormInferMeta + kernel : + func : norm + intermediate : norm + backward : norm_grad + - api : not_equal args : (Tensor x, Tensor y, int axis = -1) output : Tensor @@ -1548,6 +1558,7 @@ func : SegmentPoolInferMeta kernel : func : segment_pool + data_type : x backward : segment_pool_grad # selu diff --git a/python/paddle/utils/code_gen/backward.yaml b/python/paddle/utils/code_gen/backward.yaml index 708c754f782..3f5f6b5d748 100644 --- a/python/paddle/utils/code_gen/backward.yaml +++ b/python/paddle/utils/code_gen/backward.yaml @@ -908,6 +908,16 @@ data_type : input optional : weight +- backward_api : norm_grad + forward : norm (Tensor x, int axis, float epsilon, bool is_test) -> Tensor(out), Tensor(norm) + args : (Tensor x, Tensor norm, Tensor out_grad, int axis, float epsilon, bool is_test) + output : Tensor(x_grad) + infer_meta : + func : UnchangedInferMeta + param : [x] + kernel : + func : norm_grad + - backward_api : p_norm_grad forward : p_norm(Tensor x, float porder, int axis, float epsilon, bool keepdim, bool asvector=false) -> Tensor(out) args : (Tensor x, Tensor out, Tensor out_grad, float porder, int axis, float epsilon, bool keepdim, bool asvector) @@ -1096,7 +1106,7 @@ forward : scale (Tensor x, Scalar scale, float bias, bool bias_after_scale) -> Tensor(out) args : (Tensor out_grad, Scalar scale=1.0, float bias=0.0, bool bias_after_scale=true) output : Tensor(x_grad) - invoke : scale(out_grad, scale, bias, bias_after_scale) + invoke : scale(out_grad, scale, 0.0, bias_after_scale) - backward_api : scatter_grad forward : scatter (Tensor x, Tensor index, Tensor updates, bool overwrite) -> Tensor(out) @@ -1129,6 +1139,8 @@ param : [x] kernel : func : segment_pool_grad + data_type : x + optional : summed_ids - backward_api : selu_grad forward : selu (Tensor x, float scale, float alpha) -> Tensor(out) -- GitLab