From c28fa450261f2bbd18f4c579ec6dde0c45bfd31e Mon Sep 17 00:00:00 2001 From: CtfGo Date: Thu, 12 Jan 2023 13:02:27 +0000 Subject: [PATCH 01/14] support 0D Tensor for while_loop op --- .../fluid/operators/controlflow/while_op.cc | 10 +-- .../tests/unittests/test_zero_dim_tensor.py | 66 +++++++++++++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/paddle/fluid/operators/controlflow/while_op.cc b/paddle/fluid/operators/controlflow/while_op.cc index a5e3183774f99..248d899aa2d5d 100644 --- a/paddle/fluid/operators/controlflow/while_op.cc +++ b/paddle/fluid/operators/controlflow/while_op.cc @@ -100,12 +100,12 @@ class WhileOp : public framework::OperatorBase { auto &cond = scope.FindVar(Input(kCondition))->Get(); PADDLE_ENFORCE_EQ( - cond.dims(), - phi::make_ddim({1}), + cond.numel(), + 1, platform::errors::InvalidArgument( - "The shape of Input(Condition) of WhileOp must be 1. But now " - "the Condition's shape is ", - cond.dims().to_str(), + "The numel of Input(Condition) of WhileOp must be 1. But now " + "the Condition's numel is ", + cond.numel(), ".\n")); #ifdef PADDLE_WITH_MKLDNN diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 4023023ab5283..d7fb8718e065b 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -1460,6 +1460,72 @@ def test_repeat_interleave(self): res = self.exe.run(prog, fetch_list=[out]) self.assertEqual(res[0].shape, (3,)) + @prog_scope() + def test_while_loop(self): + def cond(i, ten): + return i < ten + + def body(i, ten): + i = i + 1 + return [i, ten] + + main_program = paddle.static.Program() + startup_program = paddle.static.Program() + with fluid.program_guard(main_program, startup_program): + i = paddle.full([], 0, 'int64') + ten = paddle.full([], 10, dtype='int64') + out = paddle.static.nn.while_loop(cond, body, [i, ten]) + + place = ( + paddle.CUDAPlace(0) + if paddle.device.is_compiled_with_cuda() + else paddle.CPUPlace() + ) + res = self.exe.run(main_program, fetch_list=out) + self.assertEqual(res[0].shape, ()) + + @prog_scope() + def test_while_loop_backward(self): + def cond(i, x): + return paddle.less_than(i, eleven) + + def body(i, x): + x = paddle.multiply(x=i, y=i) + i = paddle.increment(i) + return [i, x] + + main_program = paddle.static.Program() + startup_program = paddle.static.Program() + with fluid.program_guard(main_program, startup_program): + i = paddle.static.data(name='i', shape=[], dtype='float32') + i.stop_gradient = False + eleven = paddle.full([], 11, 'float32') + one = paddle.full([], 1, 'float32') + x = paddle.static.data(name='x', shape=[], dtype='float32') + x.stop_gradient = False + + out = paddle.static.nn.while_loop(cond, body, [i, x]) + mean = paddle.mean(out[1]) + paddle.static.append_backward(mean) + + place = ( + paddle.CUDAPlace(0) + if paddle.device.is_compiled_with_cuda() + else paddle.CPUPlace() + ) + feed_i = np.ones([]).astype('float32') + feed_x = np.ones([]).astype('float32') + data = np.array(100).astype('float32') + i_grad = np.array(110).astype('float32') + + res = self.exe.run( + main_program, + feed={'i': feed_i, 'x': feed_x}, + fetch_list=[mean.name, i.grad_name], + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[1].shape, ()) + # Use to test API whose zero-dim input tensors don't have grad and not need to test backward in OpTest. class TestNoBackwardAPI(unittest.TestCase): From 33cd838e33c8409010b720376c00e716bdd8f874 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Tue, 17 Jan 2023 07:53:35 +0000 Subject: [PATCH 02/14] update --- .../tests/unittests/test_while_loop_op.py | 16 ++++++++-------- .../tests/unittests/test_zero_dim_tensor.py | 18 +++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_while_loop_op.py b/python/paddle/fluid/tests/unittests/test_while_loop_op.py index c5c31ac571760..fde0bc48be4f1 100644 --- a/python/paddle/fluid/tests/unittests/test_while_loop_op.py +++ b/python/paddle/fluid/tests/unittests/test_while_loop_op.py @@ -236,11 +236,11 @@ def body(i, x): main_program = Program() startup_program = Program() with fluid.program_guard(main_program, startup_program): - i = fluid.data(name='i', shape=[1], dtype='float32') + i = fluid.data(name='i', shape=[], dtype='float32') i.stop_gradient = False - eleven = layers.fill_constant(shape=[1], dtype='float32', value=11) - one = layers.fill_constant(shape=[1], dtype='float32', value=1) - x = fluid.data(name='x', shape=[1], dtype='float32') + eleven = layers.fill_constant(shape=[], dtype='float32', value=11) + one = layers.fill_constant(shape=[], dtype='float32', value=1) + x = fluid.data(name='x', shape=[], dtype='float32') x.stop_gradient = False out = paddle.static.nn.while_loop(cond, body, [i, x]) @@ -254,10 +254,10 @@ def body(i, x): ) exe = fluid.Executor(place) - feed_i = np.ones(1).astype('float32') - feed_x = np.ones(1).astype('float32') - data = np.asarray([100]).astype('float32') - i_grad = np.asarray([110]).astype('float32') + feed_i = np.ones([]).astype('float32') + feed_x = np.ones([]).astype('float32') + data = np.asarray(100).astype('float32') + i_grad = np.asarray(110).astype('float32') res = exe.run( main_program, diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index d7fb8718e065b..622cfab94bfef 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -1470,19 +1470,21 @@ def body(i, ten): return [i, ten] main_program = paddle.static.Program() - startup_program = paddle.static.Program() - with fluid.program_guard(main_program, startup_program): + with fluid.program_guard(main_program, paddle.static.Program()): i = paddle.full([], 0, 'int64') + i.stop_gradient = False ten = paddle.full([], 10, dtype='int64') out = paddle.static.nn.while_loop(cond, body, [i, ten]) + paddle.static.append_backward(out[0]) place = ( paddle.CUDAPlace(0) if paddle.device.is_compiled_with_cuda() else paddle.CPUPlace() ) - res = self.exe.run(main_program, fetch_list=out) + res = self.exe.run(main_program, fetch_list=[i.name, i.grad_name]) self.assertEqual(res[0].shape, ()) + self.assertEqual(res[1].shape, ()) @prog_scope() def test_while_loop_backward(self): @@ -1505,8 +1507,8 @@ def body(i, x): x.stop_gradient = False out = paddle.static.nn.while_loop(cond, body, [i, x]) - mean = paddle.mean(out[1]) - paddle.static.append_backward(mean) + # mean = paddle.mean(out[1]) + paddle.static.append_backward(out[1]) place = ( paddle.CUDAPlace(0) @@ -1515,16 +1517,14 @@ def body(i, x): ) feed_i = np.ones([]).astype('float32') feed_x = np.ones([]).astype('float32') - data = np.array(100).astype('float32') - i_grad = np.array(110).astype('float32') res = self.exe.run( main_program, feed={'i': feed_i, 'x': feed_x}, - fetch_list=[mean.name, i.grad_name], + fetch_list=[x.name, i.grad_name], ) self.assertEqual(res[0].shape, ()) - self.assertEqual(res[1].shape, ()) + # self.assertEqual(res[1].shape, ()) # Use to test API whose zero-dim input tensors don't have grad and not need to test backward in OpTest. From 1d5d0a0fd2c3322dad0b5b1321e02db92a755493 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Wed, 18 Jan 2023 09:19:49 +0000 Subject: [PATCH 03/14] clean unit test --- .../tests/unittests/test_zero_dim_tensor.py | 48 +++---------------- 1 file changed, 7 insertions(+), 41 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 2e109b55fe7b8..2257341e14f5d 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2165,57 +2165,23 @@ def body(i, ten): i = paddle.full([], 0, 'int64') i.stop_gradient = False ten = paddle.full([], 10, dtype='int64') - out = paddle.static.nn.while_loop(cond, body, [i, ten]) - paddle.static.append_backward(out[0]) + ten.stop_gradient = False + out_i, out_ten = paddle.static.nn.while_loop(cond, body, [i, ten]) + paddle.static.append_backward(out_i.sum()) place = ( paddle.CUDAPlace(0) if paddle.device.is_compiled_with_cuda() else paddle.CPUPlace() ) - res = self.exe.run(main_program, fetch_list=[i.name, i.grad_name]) - self.assertEqual(res[0].shape, ()) - self.assertEqual(res[1].shape, ()) - - @prog_scope() - def test_while_loop_backward(self): - def cond(i, x): - return paddle.less_than(i, eleven) - - def body(i, x): - x = paddle.multiply(x=i, y=i) - i = paddle.increment(i) - return [i, x] - - main_program = paddle.static.Program() - startup_program = paddle.static.Program() - with fluid.program_guard(main_program, startup_program): - i = paddle.static.data(name='i', shape=[], dtype='float32') - i.stop_gradient = False - eleven = paddle.full([], 11, 'float32') - one = paddle.full([], 1, 'float32') - x = paddle.static.data(name='x', shape=[], dtype='float32') - x.stop_gradient = False - - out = paddle.static.nn.while_loop(cond, body, [i, x]) - # mean = paddle.mean(out[1]) - paddle.static.append_backward(out[1]) - - place = ( - paddle.CUDAPlace(0) - if paddle.device.is_compiled_with_cuda() - else paddle.CPUPlace() - ) - feed_i = np.ones([]).astype('float32') - feed_x = np.ones([]).astype('float32') - res = self.exe.run( main_program, - feed={'i': feed_i, 'x': feed_x}, - fetch_list=[x.name, i.grad_name], + fetch_list=[i.name, ten.name, i.grad_name, ten.grad_name], ) self.assertEqual(res[0].shape, ()) - # self.assertEqual(res[1].shape, ()) + self.assertEqual(res[1].shape, ()) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[3].shape, ()) # Use to test API whose zero-dim input tensors don't have grad and not need to test backward in OpTest. From 13040051c5084b6d5d5c007a50e3785ece44c7a2 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Wed, 18 Jan 2023 09:25:38 +0000 Subject: [PATCH 04/14] revert test_while_loop_op.py --- .../fluid/tests/unittests/test_while_loop_op.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_while_loop_op.py b/python/paddle/fluid/tests/unittests/test_while_loop_op.py index fde0bc48be4f1..c5c31ac571760 100644 --- a/python/paddle/fluid/tests/unittests/test_while_loop_op.py +++ b/python/paddle/fluid/tests/unittests/test_while_loop_op.py @@ -236,11 +236,11 @@ def body(i, x): main_program = Program() startup_program = Program() with fluid.program_guard(main_program, startup_program): - i = fluid.data(name='i', shape=[], dtype='float32') + i = fluid.data(name='i', shape=[1], dtype='float32') i.stop_gradient = False - eleven = layers.fill_constant(shape=[], dtype='float32', value=11) - one = layers.fill_constant(shape=[], dtype='float32', value=1) - x = fluid.data(name='x', shape=[], dtype='float32') + eleven = layers.fill_constant(shape=[1], dtype='float32', value=11) + one = layers.fill_constant(shape=[1], dtype='float32', value=1) + x = fluid.data(name='x', shape=[1], dtype='float32') x.stop_gradient = False out = paddle.static.nn.while_loop(cond, body, [i, x]) @@ -254,10 +254,10 @@ def body(i, x): ) exe = fluid.Executor(place) - feed_i = np.ones([]).astype('float32') - feed_x = np.ones([]).astype('float32') - data = np.asarray(100).astype('float32') - i_grad = np.asarray(110).astype('float32') + feed_i = np.ones(1).astype('float32') + feed_x = np.ones(1).astype('float32') + data = np.asarray([100]).astype('float32') + i_grad = np.asarray([110]).astype('float32') res = exe.run( main_program, From b67a55425798db9575c2ff5d1dc19aa208209a92 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Wed, 18 Jan 2023 11:02:07 +0000 Subject: [PATCH 05/14] test again --- .../tests/unittests/test_zero_dim_tensor.py | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 2257341e14f5d..e09f036ff9c67 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2165,7 +2165,6 @@ def body(i, ten): i = paddle.full([], 0, 'int64') i.stop_gradient = False ten = paddle.full([], 10, dtype='int64') - ten.stop_gradient = False out_i, out_ten = paddle.static.nn.while_loop(cond, body, [i, ten]) paddle.static.append_backward(out_i.sum()) @@ -2176,13 +2175,51 @@ def body(i, ten): ) res = self.exe.run( main_program, - fetch_list=[i.name, ten.name, i.grad_name, ten.grad_name], + fetch_list=[out_i.name, out_ten.name, i.grad_name], ) self.assertEqual(res[0].shape, ()) self.assertEqual(res[1].shape, ()) self.assertEqual(res[2].shape, ()) self.assertEqual(res[3].shape, ()) + @prog_scope() + def test_while_loop_backward(self): + def cond(i, x): + return paddle.less_than(i, eleven) + + def body(i, x): + x = paddle.multiply(x=i, y=i) + i = paddle.increment(i) + return [i, x] + + main_program = paddle.static.Program() + with fluid.program_guard(main_program, paddle.static.Program()): + i = paddle.static.data(name='i', shape=[], dtype='float32') + i.stop_gradient = False + eleven = paddle.full(shape=[], value=11, dtype='float32') + one = paddle.full(shape=[], value=1, dtype='float32') + x = fluid.data(name='x', shape=[], dtype='float32') + x.stop_gradient = False + + out_i, out_x = paddle.static.nn.while_loop(cond, body, [i, x]) + paddle.static.append_backward(out_x.sum()) + + place = ( + fluid.CUDAPlace(0) + if paddle.device.is_compiled_with_cuda() + else paddle.CPUPlace() + ) + exe = fluid.Executor(place) + + feed_i = np.ones([]).astype('float32') + feed_x = np.ones([]).astype('float32') + + res = exe.run( + main_program, + feed={'i': feed_i, 'x': feed_x}, + fetch_list=[out_x.name, i.grad_name], + ) + # Use to test API whose zero-dim input tensors don't have grad and not need to test backward in OpTest. class TestNoBackwardAPI(unittest.TestCase): From 51923136065856174aecdf56cf6a87d8d89c17ee Mon Sep 17 00:00:00 2001 From: CtfGo Date: Wed, 18 Jan 2023 11:04:25 +0000 Subject: [PATCH 06/14] remove invalid check --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index e09f036ff9c67..644fbf12a8275 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2180,7 +2180,6 @@ def body(i, ten): self.assertEqual(res[0].shape, ()) self.assertEqual(res[1].shape, ()) self.assertEqual(res[2].shape, ()) - self.assertEqual(res[3].shape, ()) @prog_scope() def test_while_loop_backward(self): @@ -2198,7 +2197,7 @@ def body(i, x): i.stop_gradient = False eleven = paddle.full(shape=[], value=11, dtype='float32') one = paddle.full(shape=[], value=1, dtype='float32') - x = fluid.data(name='x', shape=[], dtype='float32') + x = paddle.static.data(name='x', shape=[], dtype='float32') x.stop_gradient = False out_i, out_x = paddle.static.nn.while_loop(cond, body, [i, x]) @@ -2219,6 +2218,8 @@ def body(i, x): feed={'i': feed_i, 'x': feed_x}, fetch_list=[out_x.name, i.grad_name], ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[1].shape, ()) # Use to test API whose zero-dim input tensors don't have grad and not need to test backward in OpTest. From ec0108c28ad9c585181af087d2965f8a821acabc Mon Sep 17 00:00:00 2001 From: CtfGo Date: Wed, 18 Jan 2023 11:39:21 +0000 Subject: [PATCH 07/14] fix error --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 644fbf12a8275..73ad473088506 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2204,16 +2204,15 @@ def body(i, x): paddle.static.append_backward(out_x.sum()) place = ( - fluid.CUDAPlace(0) + paddle.CUDAPlace(0) if paddle.device.is_compiled_with_cuda() else paddle.CPUPlace() ) - exe = fluid.Executor(place) feed_i = np.ones([]).astype('float32') feed_x = np.ones([]).astype('float32') - res = exe.run( + res = self.exe.run( main_program, feed={'i': feed_i, 'x': feed_x}, fetch_list=[out_x.name, i.grad_name], From 160a85729b8e9bf33e96196995dd0e080a668744 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Wed, 18 Jan 2023 14:05:15 +0000 Subject: [PATCH 08/14] change fluid to paddle.static --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 3576fcee4e29d..7130873470fc5 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2292,7 +2292,7 @@ def body(i, ten): return [i, ten] main_program = paddle.static.Program() - with fluid.program_guard(main_program, paddle.static.Program()): + with paddle.static.program_guard(main_program, paddle.static.Program()): i = paddle.full([], 0, 'int64') i.stop_gradient = False ten = paddle.full([], 10, dtype='int64') @@ -2323,7 +2323,7 @@ def body(i, x): return [i, x] main_program = paddle.static.Program() - with fluid.program_guard(main_program, paddle.static.Program()): + with paddle.static.program_guard(main_program, paddle.static.Program()): i = paddle.static.data(name='i', shape=[], dtype='float32') i.stop_gradient = False eleven = paddle.full(shape=[], value=11, dtype='float32') From b16241f9fa53f561ddf4e7e8046cad40dd13f8f6 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Thu, 19 Jan 2023 06:28:39 +0000 Subject: [PATCH 09/14] fix paddle.full --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 7130873470fc5..7497188f9b333 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2295,7 +2295,7 @@ def body(i, ten): with paddle.static.program_guard(main_program, paddle.static.Program()): i = paddle.full([], 0, 'int64') i.stop_gradient = False - ten = paddle.full([], 10, dtype='int64') + ten = paddle.full([], 10, 'int64') out_i, out_ten = paddle.static.nn.while_loop(cond, body, [i, ten]) paddle.static.append_backward(out_i.sum()) @@ -2326,8 +2326,8 @@ def body(i, x): with paddle.static.program_guard(main_program, paddle.static.Program()): i = paddle.static.data(name='i', shape=[], dtype='float32') i.stop_gradient = False - eleven = paddle.full(shape=[], value=11, dtype='float32') - one = paddle.full(shape=[], value=1, dtype='float32') + eleven = paddle.full([], 11, 'float32') + one = paddle.full([], 1, 'float32') x = paddle.static.data(name='x', shape=[], dtype='float32') x.stop_gradient = False From ec4edf3e67dc138308fc93704009874cfeb29514 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Sat, 28 Jan 2023 09:01:17 +0000 Subject: [PATCH 10/14] merge forward and backward test --- .../tests/unittests/test_zero_dim_tensor.py | 34 ++----------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 7497188f9b333..87bafe6b45c17 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2284,36 +2284,6 @@ def test_t(self): @prog_scope() def test_while_loop(self): - def cond(i, ten): - return i < ten - - def body(i, ten): - i = i + 1 - return [i, ten] - - main_program = paddle.static.Program() - with paddle.static.program_guard(main_program, paddle.static.Program()): - i = paddle.full([], 0, 'int64') - i.stop_gradient = False - ten = paddle.full([], 10, 'int64') - out_i, out_ten = paddle.static.nn.while_loop(cond, body, [i, ten]) - paddle.static.append_backward(out_i.sum()) - - place = ( - paddle.CUDAPlace(0) - if paddle.device.is_compiled_with_cuda() - else paddle.CPUPlace() - ) - res = self.exe.run( - main_program, - fetch_list=[out_i.name, out_ten.name, i.grad_name], - ) - self.assertEqual(res[0].shape, ()) - self.assertEqual(res[1].shape, ()) - self.assertEqual(res[2].shape, ()) - - @prog_scope() - def test_while_loop_backward(self): def cond(i, x): return paddle.less_than(i, eleven) @@ -2346,10 +2316,12 @@ def body(i, x): res = self.exe.run( main_program, feed={'i': feed_i, 'x': feed_x}, - fetch_list=[out_x.name, i.grad_name], + fetch_list=[out_i.name, out_x.name, i.grad_name, x.grad_name], ) self.assertEqual(res[0].shape, ()) self.assertEqual(res[1].shape, ()) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[3].shape, ()) # Use to test API whose zero-dim input tensors don't have grad and not need to test backward in OpTest. From df4304969b8360466a4c3a4be335fb24c63cb7f6 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Tue, 31 Jan 2023 06:44:40 +0000 Subject: [PATCH 11/14] simplify code --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 9d3e7c2e69888..03253c144a2dc 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2303,7 +2303,7 @@ def cond(i, x): return paddle.less_than(i, eleven) def body(i, x): - x = paddle.multiply(x=i, y=i) + x = paddle.multiply(x, i) i = paddle.increment(i) return [i, x] @@ -2312,10 +2312,8 @@ def body(i, x): i = paddle.static.data(name='i', shape=[], dtype='float32') i.stop_gradient = False eleven = paddle.full([], 11, 'float32') - one = paddle.full([], 1, 'float32') x = paddle.static.data(name='x', shape=[], dtype='float32') x.stop_gradient = False - out_i, out_x = paddle.static.nn.while_loop(cond, body, [i, x]) paddle.static.append_backward(out_x.sum()) From 3a1ac05aca4b4c39234c1281dfef74070d63de97 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Wed, 1 Feb 2023 02:00:13 +0000 Subject: [PATCH 12/14] add precision check --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 580fd91572f9e..ae55689929c1c 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2404,7 +2404,7 @@ def cond(i, x): return paddle.less_than(i, eleven) def body(i, x): - x = paddle.multiply(x, i) + x = paddle.multiply(i, i) i = paddle.increment(i) return [i, x] @@ -2433,9 +2433,13 @@ def body(i, x): fetch_list=[out_i.name, out_x.name, i.grad_name, x.grad_name], ) self.assertEqual(res[0].shape, ()) + np.testing.assert_allclose(res[0], np.array(1.0)) self.assertEqual(res[1].shape, ()) + np.testing.assert_allclose(res[1], np.array(100)) self.assertEqual(res[2].shape, ()) + np.testing.assert_allclose(res[2], np.array(110)) self.assertEqual(res[3].shape, ()) + np.testing.assert_allclose(res[3], np.array(1.0)) # Use to test API whose zero-dim input tensors don't have grad and not need to test backward in OpTest. From dea1b145ad68747d858cd532ade9bc829b1de500 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Wed, 1 Feb 2023 07:15:04 +0000 Subject: [PATCH 13/14] fix condition var check --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index ae55689929c1c..d39b7f7969617 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2405,7 +2405,7 @@ def cond(i, x): def body(i, x): x = paddle.multiply(i, i) - i = paddle.increment(i) + i = i + 1 return [i, x] main_program = paddle.static.Program() @@ -2433,7 +2433,7 @@ def body(i, x): fetch_list=[out_i.name, out_x.name, i.grad_name, x.grad_name], ) self.assertEqual(res[0].shape, ()) - np.testing.assert_allclose(res[0], np.array(1.0)) + np.testing.assert_allclose(res[0], np.array(11)) self.assertEqual(res[1].shape, ()) np.testing.assert_allclose(res[1], np.array(100)) self.assertEqual(res[2].shape, ()) From 48e89ac403e4f001a9010aca6563f83847577cd4 Mon Sep 17 00:00:00 2001 From: CtfGo Date: Mon, 6 Feb 2023 07:56:10 +0000 Subject: [PATCH 14/14] add dygraph test --- .../tests/unittests/test_zero_dim_tensor.py | 48 +++++++++++++------ python/paddle/static/nn/control_flow.py | 4 +- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index d39b7f7969617..340e16fbfbe3a 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -1496,6 +1496,32 @@ def test_t(self): self.assertEqual(out.grad.shape, []) self.assertEqual(x.grad.shape, []) + def test_while_loop(self): + def cond(i, x): + return paddle.less_than(i, eleven) + + def body(i, x): + x = x + i + i = i + 1 + return [i, x] + + i = paddle.full([], 1.0, dtype='float32') + i.stop_gradient = False + eleven = paddle.full([], 11, dtype='float32') + x = paddle.full([], 0.0, dtype='float32') + x.stop_gradient = False + out_i, out_x = paddle.static.nn.while_loop(cond, body, [i, x]) + out_x.backward() + + self.assertEqual(out_i.shape, []) + np.testing.assert_allclose(out_i, np.array(11)) + self.assertEqual(out_x.shape, []) + np.testing.assert_allclose(out_x, np.array(55)) + self.assertEqual(i.grad.shape, []) + np.testing.assert_allclose(i.grad, np.array(10)) + self.assertEqual(x.grad.shape, []) + np.testing.assert_allclose(x.grad, np.array(1.0)) + class TestSundryAPIStatic(unittest.TestCase): def setUp(self): @@ -2404,7 +2430,7 @@ def cond(i, x): return paddle.less_than(i, eleven) def body(i, x): - x = paddle.multiply(i, i) + x = x + i i = i + 1 return [i, x] @@ -2416,28 +2442,22 @@ def body(i, x): x = paddle.static.data(name='x', shape=[], dtype='float32') x.stop_gradient = False out_i, out_x = paddle.static.nn.while_loop(cond, body, [i, x]) - paddle.static.append_backward(out_x.sum()) - - place = ( - paddle.CUDAPlace(0) - if paddle.device.is_compiled_with_cuda() - else paddle.CPUPlace() - ) - - feed_i = np.ones([]).astype('float32') - feed_x = np.ones([]).astype('float32') + paddle.static.append_backward(out_x) res = self.exe.run( main_program, - feed={'i': feed_i, 'x': feed_x}, + feed={ + 'i': np.array(1.0, dtype='float32'), + 'x': np.array(0.0, dtype='float32'), + }, fetch_list=[out_i.name, out_x.name, i.grad_name, x.grad_name], ) self.assertEqual(res[0].shape, ()) np.testing.assert_allclose(res[0], np.array(11)) self.assertEqual(res[1].shape, ()) - np.testing.assert_allclose(res[1], np.array(100)) + np.testing.assert_allclose(res[1], np.array(55)) self.assertEqual(res[2].shape, ()) - np.testing.assert_allclose(res[2], np.array(110)) + np.testing.assert_allclose(res[2], np.array(10)) self.assertEqual(res[3].shape, ()) np.testing.assert_allclose(res[3], np.array(1.0)) diff --git a/python/paddle/static/nn/control_flow.py b/python/paddle/static/nn/control_flow.py index d46c0c7c189b7..0be5f23a0368b 100644 --- a/python/paddle/static/nn/control_flow.py +++ b/python/paddle/static/nn/control_flow.py @@ -467,7 +467,7 @@ def body(i, ten): ) if _non_static_mode(): - now_cond = pre_cond.numpy()[0] + now_cond = pre_cond.numpy().item() while now_cond: output_vars = body(*loop_vars) if not isinstance(output_vars, (list, tuple)): @@ -477,7 +477,7 @@ def body(i, ten): "body in while_loop should return the same arity " "(length and structure) and types as loop_vars" ) - now_cond = cond(*output_vars).numpy()[0] + now_cond = cond(*output_vars).numpy().item() map_structure(assign_skip_lod_tensor_array, output_vars, loop_vars) return loop_vars