From 3dfa3ccfd804e4256a2e6c9003c99c182910053e Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Thu, 20 Apr 2023 02:59:36 +0000 Subject: [PATCH 01/26] add paddle.static.setitem --- python/paddle/fluid/framework.py | 4 +++- python/paddle/fluid/variable_index.py | 11 +++++++---- python/paddle/static/__init__.py | 2 ++ python/paddle/static/input.py | 12 ++++++++++++ python/paddle/static/nn/__init__.py | 1 + 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/python/paddle/fluid/framework.py b/python/paddle/fluid/framework.py index a699a2f0fe720..b43d77229cabc 100644 --- a/python/paddle/fluid/framework.py +++ b/python/paddle/fluid/framework.py @@ -2341,7 +2341,9 @@ def __getitem__(self, item): return _getitem_impl_(self, item) def __setitem__(self, item, value): - return _setitem_impl_(self, item, value) + raise RuntimeError( + "In static mode, the __seitem__ (looks like: x[index] = value) should not be used. Please use x = paddle.static.setitem(x, index, value)" + ) def get_value(self, scope=None): """ diff --git a/python/paddle/fluid/variable_index.py b/python/paddle/fluid/variable_index.py index 0d866860b314a..e82b49e30d87e 100644 --- a/python/paddle/fluid/variable_index.py +++ b/python/paddle/fluid/variable_index.py @@ -615,7 +615,7 @@ def _setitem_for_tensor_array(var, item, value): If item is case (1), we perform paddle.tensor.array_write, in other cases, we raise a NotImplementedError. """ - from ..framework import LayerHelper, core, _non_static_mode + from ..framework import core, _non_static_mode from .framework import Variable assert ( @@ -805,17 +805,20 @@ def _setitem_impl_(var, item, value): if paddle.fluid.framework._non_static_mode(): var._bump_inplace_version() - + output = var + else: + helper = paddle.fluid.layer_helper.LayerHelper('set_value', **locals()) + output = helper.create_variable_for_type_inference(dtype=var.dtype) cur_block = default_main_program().current_block() cur_block.append_op( type="set_value", inputs=inputs, - outputs={'Out': var}, + outputs={'Out': output}, attrs=attrs, inplace_map={"Input": "Out"}, ) - return var + return output # the item is a tensor of bool diff --git a/python/paddle/static/__init__.py b/python/paddle/static/__init__.py index 2828927a6b156..6ff6a00c9ff00 100644 --- a/python/paddle/static/__init__.py +++ b/python/paddle/static/__init__.py @@ -37,6 +37,7 @@ from ..fluid import Scope # noqa: F401 from .input import data # noqa: F401 from .input import InputSpec # noqa: F401 +from .input import setitem # noqa: F401 from ..tensor.creation import create_parameter # noqa: F401 from ..tensor.creation import create_global_var # noqa: F401 @@ -126,4 +127,5 @@ 'set_ipu_shard', 'ctr_metric_bundle', 'exponential_decay', + 'setitem', ] diff --git a/python/paddle/static/input.py b/python/paddle/static/input.py index af281d6394715..ca45792172404 100644 --- a/python/paddle/static/input.py +++ b/python/paddle/static/input.py @@ -18,6 +18,8 @@ from paddle.fluid.framework import convert_np_dtype_to_dtype_, static_only from paddle.fluid.layer_helper import LayerHelper +from ..fluid.variable_index import _setitem_impl_ + __all__ = [] @@ -342,3 +344,13 @@ def __eq__(self, other): def __ne__(self, other): return not self == other + + +@static_only +def setitem(x, index, value): + """ + x(Tensor): input Tensor. + index(Scalar|Tuple|List|Tensor): Where should be set value. + value(Scalar|Tensor): The value which is going to be set. + """ + return _setitem_impl_(x, index, value) diff --git a/python/paddle/static/nn/__init__.py b/python/paddle/static/nn/__init__.py index 6c528c688652e..8611624694b10 100755 --- a/python/paddle/static/nn/__init__.py +++ b/python/paddle/static/nn/__init__.py @@ -60,6 +60,7 @@ from .control_flow import cond + __all__ = [ # noqa 'fc', 'batch_norm', From c7730e58421249e0ff7dba4c8a265a5cdf10032a Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Thu, 20 Apr 2023 06:43:22 +0000 Subject: [PATCH 02/26] add some help doc --- python/paddle/static/input.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/python/paddle/static/input.py b/python/paddle/static/input.py index ca45792172404..0c23282c0fd1b 100644 --- a/python/paddle/static/input.py +++ b/python/paddle/static/input.py @@ -352,5 +352,21 @@ def setitem(x, index, value): x(Tensor): input Tensor. index(Scalar|Tuple|List|Tensor): Where should be set value. value(Scalar|Tensor): The value which is going to be set. + + [How to write index?] + 1. ':' -> slice(), + (1) a[:]=v -> setitem(a, slice(None,None,None), v) + (2) a[1::2] -> setitem(a, slice(1,None,2), v) + + 2. if there are multiple indexes for axes, use TUPLE (Not LIST) to pack them. + (1) a[1, 2]=v -> setitem(a, (1, 2), v) + (2) a[[1,2],[2,3]]=v -> setitem(a, ([1,2],[2,3]), v) + (3) a[1,:, 3] = v -> setitem(a, (1, slice(None,None,None),3), v) + (4) a[1, ..., 2]=v -> setitem(a, (1, ..., 2), v) + + 3. You can always use TUPLE as index input, even there is only one index. + (1) a[Tensor([10,10])]=v -> setitem(a, (Tensor([10,10]),), v) + (2) a[1] = v -> setitem(a, (1,), v) """ + return _setitem_impl_(x, index, value) From 5df24af6226399adca5e8ca55f7a757070677cc2 Mon Sep 17 00:00:00 2001 From: Aurelius84 Date: Sun, 23 Apr 2023 14:39:14 +0800 Subject: [PATCH 03/26] support setitem --- python/paddle/jit/dy2static/__init__.py | 1 + .../paddle/jit/dy2static/convert_operators.py | 13 ++++ .../paddle/jit/dy2static/slice_transformer.py | 61 +++++++++++++++++++ test/dygraph_to_static/test_setitem.py | 56 +++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 python/paddle/jit/dy2static/slice_transformer.py create mode 100644 test/dygraph_to_static/test_setitem.py diff --git a/python/paddle/jit/dy2static/__init__.py b/python/paddle/jit/dy2static/__init__.py index bc91a4c1674f3..06e84ea85da7d 100644 --- a/python/paddle/jit/dy2static/__init__.py +++ b/python/paddle/jit/dy2static/__init__.py @@ -23,6 +23,7 @@ from .convert_operators import convert_logical_or as Or # noqa: F401 from .convert_operators import convert_pop as Pop # noqa: F401 from .convert_operators import convert_shape as Shape # noqa: F401 +from .convert_operators import convert_setitem as SetItem # noqa: F401 from .convert_operators import convert_while_loop as While # noqa: F401 from .convert_operators import unpack_by_structure as Unpack # noqa: F401 from .convert_operators import convert_attr as Attr # noqa: F401 diff --git a/python/paddle/jit/dy2static/convert_operators.py b/python/paddle/jit/dy2static/convert_operators.py index ad9abcc9849ef..4d82bcb2c5f94 100644 --- a/python/paddle/jit/dy2static/convert_operators.py +++ b/python/paddle/jit/dy2static/convert_operators.py @@ -51,6 +51,19 @@ def convert_load(x): return x +def convert_setitem(x, index, value): + if isinstance(x, Variable): + return paddle.static.setitem(x, index, value) + elif hasattr(x, '__setitem__'): + return x.__setitem__(index, value) + else: + raise RuntimeError( + "Unsupport exec _jst.SetItem for {} because it has no __setitem__ method.".format( + x + ) + ) + + def indexable(x, code=None): if isinstance(x, Variable): return x diff --git a/python/paddle/jit/dy2static/slice_transformer.py b/python/paddle/jit/dy2static/slice_transformer.py new file mode 100644 index 0000000000000..2dcbb48e32e5b --- /dev/null +++ b/python/paddle/jit/dy2static/slice_transformer.py @@ -0,0 +1,61 @@ +# Copyright (c) 2023 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 .base_transformer import BaseTransformer +from .static_analysis import AstNodeWrapper +from .utils import ast_to_source_code, gast + +__all__ = [] + + +class SliceTransformer(BaseTransformer): + """ + This calss transforms Expr[...] = Expr into _jst.SetItem. + """ + + def __init__(self, wrapper_root): + assert isinstance( + wrapper_root, AstNodeWrapper + ), "Input non-AstNodeWrapper node for the initialization of CallTransformer." + self.wrapper_root = wrapper_root + self.root = wrapper_root.node + + def transform(self): + self.visit(self.root) + + def visit_Assign(self, node): + self.generic_visit(node) + + if self._no_need_convert(node): + return node + + assert isinstance(node.target, gast.SubScript) + target = ast_to_source_code(node.targets.value).strip() + index = ast_to_source_code(node.targets.slice).strip() + value = ast_to_source_code(node.value).strip() + new_func_str = f"_jst.SetItem({target}, {index}, {value})" + new_value_node = gast.parse(new_func_str).body[0].value + node.value = new_value_node + + return node + + def _no_need_convert(self, node): + """ + Return True if node.target is not Subscript + """ + flag = False + if isinstance(node, gast.Assign): + flag = isinstance(node.target, gast.SubScript) + + return flag diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py new file mode 100644 index 0000000000000..e8b511644397e --- /dev/null +++ b/test/dygraph_to_static/test_setitem.py @@ -0,0 +1,56 @@ +# Copyright (c) 2023 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. + +import unittest + +import paddle + + +class TestSetItem(unittest.TestCase): + def setUp(self) -> None: + pass + + def init_data(self): + paddle.seed(2023) + x = paddle.randn([4, 8]) + x.stop_gradient = False + return x + + def test_case1(self): + def foo(x): + y = x + 1 + y[:, 2] = x[:, 2] + 1 + # y = paddle.fluid.framework._setitem_impl_(y, (slice(None,None,None), 2) , x[:, 2]+1) + return y + + # dy_res = self.run_dygrah(foo) + st_res = self.run_to_static(foo) + + # for dy_out, st_out in zip(dy_res, st_res): + # np.testing.assert_allclose(dy_out.numpy, st_out.numpy()) + + def run_dygrah(self, func): + x = self.init_data() + y = func(x) + x_grad = paddle.grad(y, x)[0] + print(y, x_grad) + return y, x_grad + + def run_to_static(self, func): + func = paddle.jit.to_static(func) + return self.run_dygrah(func) + + +if __name__ == '__main__': + unittest.main() From 9ada910c6238156f1ebd0690d49eb6415c5c65ef Mon Sep 17 00:00:00 2001 From: Aurelius84 Date: Sun, 23 Apr 2023 08:30:56 +0000 Subject: [PATCH 04/26] support machanism --- python/paddle/fluid/variable_index.py | 8 ++- python/paddle/jit/dy2static/__init__.py | 2 +- .../paddle/jit/dy2static/ast_transformer.py | 2 + .../paddle/jit/dy2static/slice_transformer.py | 52 ++++++++++++------- test/dygraph_to_static/test_setitem.py | 24 +++++---- 5 files changed, 56 insertions(+), 32 deletions(-) diff --git a/python/paddle/fluid/variable_index.py b/python/paddle/fluid/variable_index.py index 0d866860b314a..dec416decd901 100644 --- a/python/paddle/fluid/variable_index.py +++ b/python/paddle/fluid/variable_index.py @@ -805,17 +805,21 @@ def _setitem_impl_(var, item, value): if paddle.fluid.framework._non_static_mode(): var._bump_inplace_version() + output = var + else: + helper = paddle.fluid.layer_helper.LayerHelper('set_value', **locals()) + output = helper.create_variable_for_type_inference(dtype=var.dtype) cur_block = default_main_program().current_block() cur_block.append_op( type="set_value", inputs=inputs, - outputs={'Out': var}, + outputs={'Out': output}, attrs=attrs, inplace_map={"Input": "Out"}, ) - return var + return output # the item is a tensor of bool diff --git a/python/paddle/jit/dy2static/__init__.py b/python/paddle/jit/dy2static/__init__.py index 06e84ea85da7d..366e8fe8f5b6d 100644 --- a/python/paddle/jit/dy2static/__init__.py +++ b/python/paddle/jit/dy2static/__init__.py @@ -23,7 +23,6 @@ from .convert_operators import convert_logical_or as Or # noqa: F401 from .convert_operators import convert_pop as Pop # noqa: F401 from .convert_operators import convert_shape as Shape # noqa: F401 -from .convert_operators import convert_setitem as SetItem # noqa: F401 from .convert_operators import convert_while_loop as While # noqa: F401 from .convert_operators import unpack_by_structure as Unpack # noqa: F401 from .convert_operators import convert_attr as Attr # noqa: F401 @@ -33,6 +32,7 @@ from .variable_trans_func import to_static_variable # noqa: F401 from .convert_operators import convert_shape_compare # noqa: F401 from .assert_transformer import AssertTransformer +from .slice_transformer import GetSetter as GSet # noqa: F401 from .ast_transformer import DygraphToStaticAst from .program_translator import convert_to_static from .static_analysis import AstNodeWrapper, NodeVarType, StaticAnalysisVisitor diff --git a/python/paddle/jit/dy2static/ast_transformer.py b/python/paddle/jit/dy2static/ast_transformer.py index 3626709bc3714..1607f957040a3 100644 --- a/python/paddle/jit/dy2static/ast_transformer.py +++ b/python/paddle/jit/dy2static/ast_transformer.py @@ -36,6 +36,7 @@ from .logical_transformer import LogicalTransformer from .loop_transformer import LoopTransformer from .return_transformer import ReturnTransformer +from .slice_transformer import SliceTransformer from .static_analysis import StaticAnalysisVisitor from .tensor_shape_transformer import TensorShapeTransformer from .typehint_transformer import TypeHintTransformer @@ -92,6 +93,7 @@ def transfer_from_node_type(self, node_wrapper): self.visit(node_wrapper.node) transformers = [ + SliceTransformer, EarlyReturnTransformer, BasicApiTransformer, # Basic Api TensorShapeTransformer, # Tensor.shape -> paddle.shape(Tensor) diff --git a/python/paddle/jit/dy2static/slice_transformer.py b/python/paddle/jit/dy2static/slice_transformer.py index 2dcbb48e32e5b..a972df391c8cf 100644 --- a/python/paddle/jit/dy2static/slice_transformer.py +++ b/python/paddle/jit/dy2static/slice_transformer.py @@ -12,6 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +import paddle +from paddle.fluid.framework import Variable + from .base_transformer import BaseTransformer from .static_analysis import AstNodeWrapper from .utils import ast_to_source_code, gast @@ -19,9 +22,34 @@ __all__ = [] +class GetSetter: + """ + GetSetter is a Proxy class implenenting Python getter / setter magic method. It's basic unit + for _jst.GSet(...) to make us not care what ast is like. + """ + + def __init__(self, obj): + self.obj = obj + + def __getitem__(self, item): + return self.obj[item] + + def __setitem__(self, item, value): + if isinstance(self.obj, Variable): + return paddle.fluid.framework._setitem_impl_(self.obj, item, value) + elif hasattr(self.obj, '__setitem__'): + return self.obj.__setitem__(item, value) + else: + raise RuntimeError( + "Unsupport _jst.GSet for {} because it has no __setitem__ method.".format( + self.obj + ) + ) + + class SliceTransformer(BaseTransformer): """ - This calss transforms Expr[...] = Expr into _jst.SetItem. + This calss transforms Expr[...] = Expr into _jst.GSet(Expr)[...] = Expr. """ def __init__(self, wrapper_root): @@ -34,28 +62,12 @@ def __init__(self, wrapper_root): def transform(self): self.visit(self.root) - def visit_Assign(self, node): + def visit_Subscript(self, node): self.generic_visit(node) - if self._no_need_convert(node): - return node - - assert isinstance(node.target, gast.SubScript) - target = ast_to_source_code(node.targets.value).strip() - index = ast_to_source_code(node.targets.slice).strip() value = ast_to_source_code(node.value).strip() - new_func_str = f"_jst.SetItem({target}, {index}, {value})" - new_value_node = gast.parse(new_func_str).body[0].value + new_value_str = f"_jst.GSet({value})" + new_value_node = gast.parse(new_value_str).body[0].value node.value = new_value_node return node - - def _no_need_convert(self, node): - """ - Return True if node.target is not Subscript - """ - flag = False - if isinstance(node, gast.Assign): - flag = isinstance(node.target, gast.SubScript) - - return flag diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py index e8b511644397e..a06429dd19ff5 100644 --- a/test/dygraph_to_static/test_setitem.py +++ b/test/dygraph_to_static/test_setitem.py @@ -14,37 +14,43 @@ import unittest +import numpy as np + import paddle -class TestSetItem(unittest.TestCase): +class TestSetItemBase(unittest.TestCase): def setUp(self) -> None: pass def init_data(self): paddle.seed(2023) - x = paddle.randn([4, 8]) + x = paddle.randn([4, 8, 16, 32]) x.stop_gradient = False return x - def test_case1(self): + def init_func(self): def foo(x): y = x + 1 y[:, 2] = x[:, 2] + 1 - # y = paddle.fluid.framework._setitem_impl_(y, (slice(None,None,None), 2) , x[:, 2]+1) + # breakpoint() return y - # dy_res = self.run_dygrah(foo) - st_res = self.run_to_static(foo) + return foo + + def test_case(self): + func = self.init_func() + dy_res = self.run_dygrah(func) + st_res = self.run_to_static(func) - # for dy_out, st_out in zip(dy_res, st_res): - # np.testing.assert_allclose(dy_out.numpy, st_out.numpy()) + for dy_out, st_out in zip(dy_res, st_res): + np.testing.assert_allclose(dy_out.numpy(), st_out.numpy()) def run_dygrah(self, func): x = self.init_data() y = func(x) x_grad = paddle.grad(y, x)[0] - print(y, x_grad) + # print(y, x_grad) return y, x_grad def run_to_static(self, func): From 44944b2516011c291130632d75ebc9d1824cd327 Mon Sep 17 00:00:00 2001 From: Aurelius84 Date: Mon, 24 Apr 2023 02:34:00 +0000 Subject: [PATCH 05/26] add more unittest --- test/dygraph_to_static/test_setitem.py | 95 +++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py index a06429dd19ff5..cc8fbbff2bb24 100644 --- a/test/dygraph_to_static/test_setitem.py +++ b/test/dygraph_to_static/test_setitem.py @@ -33,7 +33,6 @@ def init_func(self): def foo(x): y = x + 1 y[:, 2] = x[:, 2] + 1 - # breakpoint() return y return foo @@ -50,7 +49,6 @@ def run_dygrah(self, func): x = self.init_data() y = func(x) x_grad = paddle.grad(y, x)[0] - # print(y, x_grad) return y, x_grad def run_to_static(self, func): @@ -58,5 +56,98 @@ def run_to_static(self, func): return self.run_dygrah(func) +class TestCase1(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[2] = x[2] + 1 # (2, ) + return y + + return foo + + +class TestCase2(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[:] = x[:] + 1 # slice(None,None,None) + return y + + return foo + + +class TestCase3(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[1::2] = x[1::2] + 1 # slice(1,None,2) + return y + + return foo + + +class TestCase4(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[1, 2] = x[1, 2] + 1 # (1, 2) + return y + + return foo + + +class TestCase5(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[[1, 2], [2, 3]] = x[[1, 2], [2, 3]] + 1 # ([1,2],[2,3]) + return y + + return foo + + +class TestCase6(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[1, :, 3] = x[1, :, 3] + 1 # slice(None,None,None),3) + return y + + return foo + + +class TestCase7(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[1, ..., 2] = x[1, ..., 2] + 1 # (1, ..., 2) + return y + + return foo + + +class TestCase8(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + index = paddle.to_tensor([1, 2], dtype="int64") + y[index] = x[index] + 1 # Tensor([1,2]) + return y + + return foo + + +class TestCase9(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + one = paddle.to_tensor([1], dtype="int64") + two = paddle.to_tensor([2], dtype="int64") + y[one, :, :, 2] = x[1, :, :, two] + 1 # Tensor([1]), Tensor([2]) + return y + + return foo + + if __name__ == '__main__': unittest.main() From aa0247f28bbde26fdf728e89688cab3aca41839d Mon Sep 17 00:00:00 2001 From: Aurelius84 Date: Mon, 24 Apr 2023 03:04:22 +0000 Subject: [PATCH 06/26] remove usless code --- python/paddle/jit/dy2static/convert_operators.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/python/paddle/jit/dy2static/convert_operators.py b/python/paddle/jit/dy2static/convert_operators.py index 4d82bcb2c5f94..ad9abcc9849ef 100644 --- a/python/paddle/jit/dy2static/convert_operators.py +++ b/python/paddle/jit/dy2static/convert_operators.py @@ -51,19 +51,6 @@ def convert_load(x): return x -def convert_setitem(x, index, value): - if isinstance(x, Variable): - return paddle.static.setitem(x, index, value) - elif hasattr(x, '__setitem__'): - return x.__setitem__(index, value) - else: - raise RuntimeError( - "Unsupport exec _jst.SetItem for {} because it has no __setitem__ method.".format( - x - ) - ) - - def indexable(x, code=None): if isinstance(x, Variable): return x From 788f8ac04289092edb371deb316ca56ffde0cde5 Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Wed, 10 May 2023 06:58:07 +0000 Subject: [PATCH 07/26] raise error in static setitem --- python/paddle/fluid/framework.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/paddle/fluid/framework.py b/python/paddle/fluid/framework.py index 184d6cb326e5b..5528899f8609c 100644 --- a/python/paddle/fluid/framework.py +++ b/python/paddle/fluid/framework.py @@ -2328,7 +2328,9 @@ def __getitem__(self, item): return _getitem_impl_(self, item) def __setitem__(self, item, value): - return _setitem_impl_(self, item, value) + raise RuntimeError( + "In static mode, the __setitem__ (looks like: x[index] = value) should not be used. Please use x = paddle.static.setitem(x, index, value)" + ) def get_value(self, scope=None): """ From c4853e0ef31e1a4e7470db01b88b8b0da9ac7e2f Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Thu, 11 May 2023 08:08:11 +0000 Subject: [PATCH 08/26] fix d2s UT --- python/paddle/fluid/variable_index.py | 6 ++++-- test/dygraph_to_static/test_setitem.py | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/python/paddle/fluid/variable_index.py b/python/paddle/fluid/variable_index.py index 19af1d9a56747..03ea61acb3e22 100644 --- a/python/paddle/fluid/variable_index.py +++ b/python/paddle/fluid/variable_index.py @@ -216,7 +216,9 @@ def set_item(self, tensor_origin, value): out = paddle.scatter(t_reshape, index_1d, value_1d) if tensor_type is not None: out = out.astype(tensor_type) - tensor_origin[:] = out.reshape(tensor_origin.shape) + tensor_origin = _setitem_impl_( + tensor_origin, ..., out.reshape(tensor_origin.shape) + ) return tensor_origin @@ -855,7 +857,7 @@ def idx_not_empty(var, item, value): gather_val = gather_nd(var, idx) gather_val_new = value - gather_val out = scatter_nd_add(var, idx, gather_val_new) - var[:] = out + var = _setitem_impl_(var, ..., out) from paddle.static.nn import cond diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py index cc8fbbff2bb24..2bf8219028dbc 100644 --- a/test/dygraph_to_static/test_setitem.py +++ b/test/dygraph_to_static/test_setitem.py @@ -141,9 +141,9 @@ class TestCase9(TestSetItemBase): def init_func(self): def foo(x): y = x + 1 - one = paddle.to_tensor([1], dtype="int64") - two = paddle.to_tensor([2], dtype="int64") - y[one, :, :, 2] = x[1, :, :, two] + 1 # Tensor([1]), Tensor([2]) + one = paddle.to_tensor(1, dtype="int64") + two = paddle.to_tensor(2, dtype="int64") + y[one, :, :, 2] = x[1, :, :, two] + 1 # Tensor(1), Tensor(2) return y return foo From 4218a9617610f6e28acbac1e749461b632ac7e1a Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Tue, 16 May 2023 13:38:55 +0000 Subject: [PATCH 09/26] remove static only for both-used code --- .../incubate/optimizer/functional/lbfgs.py | 21 +++++++++++-------- python/paddle/static/input.py | 1 - 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/python/paddle/incubate/optimizer/functional/lbfgs.py b/python/paddle/incubate/optimizer/functional/lbfgs.py index e3620c4ffc0ed..320c4bc13d06a 100644 --- a/python/paddle/incubate/optimizer/functional/lbfgs.py +++ b/python/paddle/incubate/optimizer/functional/lbfgs.py @@ -178,16 +178,20 @@ def body( shape=[], fill_value=(head - 1).mod(history_size), dtype='int64' ) - def cond(i, q): + def cond(i, q, ai_vec): return i != tail - def body(i, q): - ai_vec[i] = rhok_vec[i] * paddle.dot(sk_vec[i], q) + def body(i, q, ai_vec): + ai_vec = paddle.static.setitem( + ai_vec, i, rhok_vec[i] * paddle.dot(sk_vec[i], q) + ) q = q - ai_vec[i] * yk_vec[i] i = (i - 1).mod(history_size) - return i, q + return i, q, ai_vec - paddle.static.nn.while_loop(cond=cond, body=body, loop_vars=[i, q]) + paddle.static.nn.while_loop( + cond=cond, body=body, loop_vars=[i, q, ai_vec] + ) r = paddle.matmul(H0, q) @@ -233,10 +237,9 @@ def body(i, r): lambda: paddle.full(shape=[1], fill_value=1000.0, dtype=dtype), lambda: 1.0 / rhok_inv, ) - - sk_vec[head] = sk - yk_vec[head] = yk - rhok_vec[head] = rhok + sk_vec = paddle.static.setitem(sk_vec, head, sk) + yk_vec = paddle.static.setitem(yk_vec, head, yk) + rhok_vec = paddle.static.setitem(rhok_vec, head, rhok) head = (head + 1) % history_size def true_fn(tail): diff --git a/python/paddle/static/input.py b/python/paddle/static/input.py index 0c23282c0fd1b..ab8f80c8879aa 100644 --- a/python/paddle/static/input.py +++ b/python/paddle/static/input.py @@ -346,7 +346,6 @@ def __ne__(self, other): return not self == other -@static_only def setitem(x, index, value): """ x(Tensor): input Tensor. From 69da71aa0512ec57ff7c4489c148a418f2ed86cd Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Tue, 16 May 2023 13:40:01 +0000 Subject: [PATCH 10/26] fix bool set_value in static, fix set_value_op UT --- .../tests/unittests/test_program_converter.py | 25 +- .../tests/unittests/test_set_value_op.py | 352 ++++++++++++++++-- python/paddle/fluid/variable_index.py | 10 +- 3 files changed, 352 insertions(+), 35 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_program_converter.py b/python/paddle/fluid/tests/unittests/test_program_converter.py index a9926b8c5c6d6..9a9c49df01b68 100644 --- a/python/paddle/fluid/tests/unittests/test_program_converter.py +++ b/python/paddle/fluid/tests/unittests/test_program_converter.py @@ -81,7 +81,8 @@ def test_int32(self): with paddle.static.program_guard(mp, sp): x = paddle.ones([3, 4], dtype=paddle.int32) patch = np.array([41, 42]).astype(np.int32) - x[:1, :2] = patch + index = (slice(None, 1), slice(None, 2)) + x = paddle.static.setitem(x, index, patch) x_input = np.ones([3, 4], dtype=np.int32) x_output = x_input.copy() @@ -110,10 +111,12 @@ def test_int64(self): patch = np.array( [np.iinfo(np.int64).max, np.iinfo(np.int64).min] ).astype(np.int64) - x[:1, :2] = patch + index = (slice(None, 1), slice(None, 2)) + x = paddle.static.setitem(x, index, patch) x_input = np.ones([3, 4], dtype=np.int64) x_output = x_input.copy() + x_output[:1, :2] = patch self.fetch_list = [x.name] @@ -142,7 +145,8 @@ def test_float32(self): patch = np.array( [np.finfo(np.float32).max, np.finfo(np.float32).min] ).astype(np.float32) - x[:1, :2] = patch + index = (slice(None, 1), slice(None, 2)) + x = paddle.static.setitem(x, index, patch) x_input = np.ones([3, 4], dtype=np.float32) x_output = x_input.copy() @@ -171,7 +175,8 @@ def test_float64(self): patch = np.array( [np.finfo(np.float64).max, np.finfo(np.float64).min] ).astype(np.float64) - x[:1, :2] = patch + index = (slice(None, 1), slice(None, 2)) + x = paddle.static.setitem(x, index, patch) x_input = np.ones([3, 4], dtype=np.float64) x_output = x_input.copy() @@ -200,7 +205,8 @@ def test_float16(self): patch = np.array( [np.finfo(np.float16).max, np.finfo(np.float16).min] ).astype(np.float16) - x[:1, :2] = patch + index = (slice(None, 1), slice(None, 2)) + x = paddle.static.setitem(x, index, patch) x_input = np.ones([3, 4], dtype=np.float16) x_output = x_input.copy() @@ -227,7 +233,8 @@ def test_bool(self): with paddle.static.program_guard(mp, sp): x = paddle.ones([3, 4], dtype=paddle.bool) patch = np.array([True, False]) - x[:1, :2] = patch + index = (slice(None, 1), slice(None, 2)) + x = paddle.static.setitem(x, index, patch) x_input = np.ones([3, 4], dtype=bool) x_output = x_input.copy() @@ -257,7 +264,8 @@ def test_complex64(self): paddle.ones([3, 4], dtype=paddle.float32), ) patch = np.array([42.1 + 42.1j, 42.2 + 42.2j]).astype(np.complex64) - x[:1, :2] = patch + index = (slice(None, 1), slice(None, 2)) + x = paddle.static.setitem(x, index, patch) x_input = (np.ones([3, 4]) + 1j * np.ones([3, 4])).astype(np.complex64) x_output = x_input.copy() @@ -282,7 +290,8 @@ def test_complex128(self): np.finfo(np.float64).min + 1j * np.finfo(np.float64).max, ] ).astype(np.complex128) - x[:1, :2] = patch + index = (slice(None, 1), slice(None, 2)) + x = paddle.static.setitem(x, index, patch) x_input = (np.ones([3, 4]) + 1j * np.ones([3, 4])).astype(np.complex128) x_output = x_input.copy() diff --git a/python/paddle/fluid/tests/unittests/test_set_value_op.py b/python/paddle/fluid/tests/unittests/test_set_value_op.py index c2dde3a258d98..7c11cdbd889ef 100644 --- a/python/paddle/fluid/tests/unittests/test_set_value_op.py +++ b/python/paddle/fluid/tests/unittests/test_set_value_op.py @@ -46,6 +46,10 @@ def set_dtype(self): def _call_setitem(self, x): x[0, 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, 0), self.value) + return x + def _get_answer(self): self.data[0, 0] = self.value @@ -55,7 +59,7 @@ def _run_static(self): paddle.enable_static() with paddle.static.program_guard(self.program): x = paddle.ones(shape=self.shape, dtype=self.dtype) - self._call_setitem(x) + x = self._call_setitem_static_api(x) exe = paddle.static.Executor(paddle.CPUPlace()) out = exe.run(self.program, fetch_list=[x]) @@ -94,6 +98,10 @@ class TestSetValueItemInt(TestSetValueApi): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -104,6 +112,10 @@ class TestSetValueItemSlice(TestSetValueApi): def _call_setitem(self, x): x[0:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 2), self.value) + return x + def _get_answer(self): self.data[0:2] = self.value @@ -112,6 +124,10 @@ class TestSetValueItemSlice2(TestSetValueApi): def _call_setitem(self, x): x[0:-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, -1), self.value) + return x + def _get_answer(self): self.data[0:-1] = self.value @@ -120,6 +136,10 @@ class TestSetValueItemSlice3(TestSetValueApi): def _call_setitem(self, x): x[0:-1, 0:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(0, -1), slice(0, 2)), self.value) + return x + def _get_answer(self): self.data[0:-1, 0:2] = self.value @@ -128,6 +148,12 @@ class TestSetValueItemSlice4(TestSetValueApi): def _call_setitem(self, x): x[0:, 1:2, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), slice(1, 2), slice(None)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:2, :] = self.value @@ -136,6 +162,12 @@ class TestSetValueItemSlice5(TestSetValueApi): def _call_setitem(self, x): x[0:, 1:1, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), slice(1, 1), slice(None)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:1, :] = self.value @@ -153,6 +185,19 @@ def body(i, x): i = paddle.zeros(shape=(1,), dtype='int32') i, x = paddle.static.nn.while_loop(cond, body, [i, x]) + def _call_setitem_static_api(self, x): + def cond(i, x): + return i < 1 + + def body(i, x): + x = paddle.static.setitem(x, i, self.value) + i = i + 1 + return i, x + + i = paddle.zeros(shape=(1,), dtype='int32') + i, x = paddle.static.nn.while_loop(cond, body, [i, x]) + return x + def _get_answer(self): self.data[0] = self.value @@ -165,6 +210,10 @@ def set_shape(self): def _call_setitem(self, x): x[0:2:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 2, 2), self.value) + return x + def _get_answer(self): self.data[0:2:2] = self.value @@ -176,6 +225,10 @@ def set_shape(self): def _call_setitem(self, x): x[0:-1:3] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, -1, 3), self.value) + return x + def _get_answer(self): self.data[0:-1:3] = self.value @@ -184,6 +237,12 @@ class TestSetValueItemSliceStep3(TestSetValueApi): def _call_setitem(self, x): x[0:-1, 0:2, ::2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, -1), slice(0, 2), slice(None, None, 2)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2, ::2] = self.value @@ -192,6 +251,12 @@ class TestSetValueItemSliceStep4(TestSetValueApi): def _call_setitem(self, x): x[0:, 1:2:2, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), slice(1, 2, 2), slice(None)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:2:2, :] = self.value @@ -207,6 +272,10 @@ def set_value(self): def _call_setitem(self, x): x[5:2:-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(5, 2, -1), self.value) + return x + def _get_answer(self): self.data[5:2:-1] = self.value @@ -221,6 +290,10 @@ def set_value(self): def _call_setitem(self, x): x[1::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(1, None, -1), self.value) + return x + def _get_answer(self): self.data[1::-1] = self.value @@ -235,6 +308,10 @@ def set_value(self): def _call_setitem(self, x): x[::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(None, None, -1), self.value) + return x + def _get_answer(self): self.data[::-1] = self.value @@ -246,6 +323,12 @@ def set_shape(self): def _call_setitem(self, x): x[2:0:-1, 0:2, ::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(2, 0, -1), slice(0, 2), slice(None, None, -1)), self.value + ) + return x + def _get_answer(self): self.data[2:0:-1, 0:2, ::-1] = self.value @@ -257,6 +340,12 @@ class TestSetValueItemEllipsis1(TestSetValueApi): def _call_setitem(self, x): x[0:, ..., 1:] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), ..., slice(1, None)), self.value + ) + return x + def _get_answer(self): self.data[0:, ..., 1:] = self.value @@ -265,6 +354,10 @@ class TestSetValueItemEllipsis2(TestSetValueApi): def _call_setitem(self, x): x[0:, ...] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(0, None), ...), self.value) + return x + def _get_answer(self): self.data[0:, ...] = self.value @@ -273,6 +366,10 @@ class TestSetValueItemEllipsis3(TestSetValueApi): def _call_setitem(self, x): x[..., 1:] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (..., slice(1, None)), self.value) + return x + def _get_answer(self): self.data[..., 1:] = self.value @@ -281,6 +378,10 @@ class TestSetValueItemEllipsis4(TestSetValueApi): def _call_setitem(self, x): x[...] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, ..., self.value) + return x + def _get_answer(self): self.data[...] = self.value @@ -288,49 +389,84 @@ def _get_answer(self): # 1.4 item is Paddle Tensor class TestSetValueItemTensor(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") + zero = paddle.full([], 0, dtype="int32") x[zero] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + x = paddle.static.setitem(x, zero, self.value) + return x + def _get_answer(self): self.data[0] = self.value class TestSetValueItemTensor2(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") - two = paddle.full([1], 2, dtype="int64") + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") x[zero:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") + x = paddle.static.setitem(x, slice(zero, two), self.value) + return x + def _get_answer(self): self.data[0:2] = self.value class TestSetValueItemTensor3(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") - two = paddle.full([1], 2, dtype="int64") + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") x[zero:-1, 0:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") + x = paddle.static.setitem( + x, (slice(zero, -1), slice(0, two)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2] = self.value class TestSetValueItemTensor4(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") - two = paddle.full([1], 2, dtype="int64") + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") x[0:-1, zero:2, 0:6:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") + x = paddle.static.setitem( + x, (slice(0, -1), slice(zero, 2), slice(0, 6, two)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2, ::2] = self.value class TestSetValueItemTensor5(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") - two = paddle.full([1], 2, dtype="int64") + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") x[zero:, 1:2:two, :] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") + x = paddle.static.setitem( + x, (slice(zero, None), slice(1, 2, two)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:2:2, :] = self.value @@ -340,10 +476,20 @@ def set_shape(self): self.shape = [3, 4, 5] def _call_setitem(self, x): - minus1 = paddle.full([1], -1, dtype="int32") - zero = paddle.full([1], 0, dtype="int32") + minus1 = paddle.full([], -1, dtype="int32") + zero = paddle.full([], 0, dtype="int32") x[2:zero:minus1, 0:2, 10:-6:minus1] = self.value + def _call_setitem_static_api(self, x): + minus1 = paddle.full([], -1, dtype="int32") + zero = paddle.full([], 0, dtype="int64") + x = paddle.static.setitem( + x, + (slice(2, zero, minus1), slice(0, 2), slice(10, -6, minus1)), + self.value, + ) + return x + def _get_answer(self): self.data[2:0:-1, 0:2, ::-1] = self.value @@ -353,6 +499,10 @@ class TestSetValueItemNone1(TestSetValueApi): def _call_setitem(self, x): x[None] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, None, self.value) + return x + def _get_answer(self): self.data[None] = self.value @@ -361,6 +511,10 @@ class TestSetValueItemNone2(TestSetValueApi): def _call_setitem(self, x): x[0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, None, 1] = self.value @@ -369,6 +523,10 @@ class TestSetValueItemNone3(TestSetValueApi): def _call_setitem(self, x): x[:, None, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(None), None, None, 1), self.value) + return x + def _get_answer(self): self.data[:, None, None, 1] = self.value @@ -377,6 +535,10 @@ class TestSetValueItemNone4(TestSetValueApi): def _call_setitem(self, x): x[0, 0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, 0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, 0, None, 1] = self.value @@ -385,6 +547,10 @@ class TestSetValueItemNone5(TestSetValueApi): def _call_setitem(self, x): x[0, None, 0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, None, 0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, None, 0, None, 1] = self.value @@ -393,6 +559,10 @@ class TestSetValueItemNone6(TestSetValueApi): def _call_setitem(self, x): x[None, 0, 0, None, 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (None, 0, 0, None, 0), self.value) + return x + def _get_answer(self): self.data[None, 0, 0, None, 0] = self.value @@ -401,6 +571,12 @@ class TestSetValueItemNone7(TestSetValueApi): def _call_setitem(self, x): x[:, None, 1] = np.zeros(self.shape)[:, None, 0] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(None), None, 1), np.zeros(self.shape)[:, None, 0] + ) + return x + def _get_answer(self): self.data[:, None, 1] = np.zeros(self.shape)[:, None, 0] @@ -409,6 +585,12 @@ class TestSetValueItemNone8(TestSetValueApi): def _call_setitem(self, x): x[:, 1, None] = np.zeros(self.shape)[:, 0, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(None), 1, None), np.zeros(self.shape)[:, 0, None] + ) + return x + def _get_answer(self): self.data[:, 1, None] = np.zeros(self.shape)[:, 0, None] @@ -417,6 +599,14 @@ class TestSetValueItemNone9(TestSetValueApi): def _call_setitem(self, x): x[None, :, 1, ..., None] = np.zeros(self.shape)[0, 0, :, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (None, slice(None), 1, ..., None), + np.zeros(self.shape)[0, 0, :, None], + ) + return x + def _get_answer(self): self.data[None, :, 1, ..., None] = np.zeros(self.shape)[0, 0, :, None] @@ -425,15 +615,31 @@ class TestSetValueItemNone10(TestSetValueApi): def _call_setitem(self, x): x[..., None, :, None] = np.zeros(self.shape)[..., None, :, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (..., None, slice(None), None), + np.zeros(self.shape)[..., None, :, None], + ) + return x + def _get_answer(self): self.data[..., None, :, None] = np.zeros(self.shape)[..., None, :, None] -# 1.5 item is list or Tensor of bol +# 1.5 item is list or Tensor of bool +# NOTE(zoooo0820): Currently, 1-D List is same to Tuple. +# The semantic of index will be modified later。 + + class TestSetValueItemBool1(TestSetValueApi): def _call_setitem(self, x): x[[True, False]] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [True, False], self.value) + return x + def _get_answer(self): self.data[[True, False]] = self.value @@ -442,6 +648,10 @@ class TestSetValueItemBool2(TestSetValueApi): def _call_setitem(self, x): x[[False, False]] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [False, False], self.value) + return x + def _get_answer(self): self.data[[False, False]] = self.value @@ -450,6 +660,10 @@ class TestSetValueItemBool3(TestSetValueApi): def _call_setitem(self, x): x[[False, True]] = np.zeros(self.shape[2]) + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [False, True], np.zeros(self.shape[2])) + return x + def _get_answer(self): self.data[[False, True]] = np.zeros(self.shape[2]) @@ -459,6 +673,11 @@ def _call_setitem(self, x): idx = paddle.assign(np.array([False, True])) x[idx] = np.zeros(self.shape[2]) + def _call_setitem_static_api(self, x): + idx = paddle.assign(np.array([False, True])) + x = paddle.static.setitem(x, idx, np.zeros(self.shape[2])) + return x + def _get_answer(self): self.data[np.array([False, True])] = np.zeros(self.shape[2]) @@ -470,6 +689,13 @@ def _call_setitem(self, x): ) x[idx] = self.value + def _call_setitem_static_api(self, x): + idx = paddle.assign( + np.array([[False, True, False], [True, True, False]]) + ) + x = paddle.static.setitem(x, idx, self.value) + return x + def _get_answer(self): self.data[ np.array([[False, True, False], [True, True, False]]) @@ -481,6 +707,11 @@ def _call_setitem(self, x): x[0, ...] = 0 x[x > 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, ...), 0) + x = paddle.static.setitem(x, x > 0, self.value) + return x + def _get_answer(self): self.data[0, ...] = 0 self.data[self.data > 0] = self.value @@ -803,9 +1034,14 @@ def set_dtype(self): self.dtype = "int32" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -827,9 +1063,14 @@ def set_dtype(self): self.dtype = "int64" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -851,9 +1092,14 @@ def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -875,9 +1121,14 @@ def set_dtype(self): self.dtype = "float64" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -899,9 +1150,14 @@ def set_dtype(self): self.dtype = "bool" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=False, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=False, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=False, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = False @@ -925,6 +1181,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -936,6 +1196,10 @@ def set_value(self): def _call_setitem(self, x): x[0:1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 1), self.value) + return x + def _get_answer(self): self.data[0:1] = self.value @@ -949,6 +1213,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -964,6 +1232,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = paddle.assign(self.value) # x is Paddle.Tensor + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, paddle.assign(self.value)) + return x + def _get_answer(self): self.data[0] = self.value @@ -978,6 +1250,12 @@ def set_shape(self): def _call_setitem(self, x): x[:, 0] = paddle.assign(self.value) # x is Paddle.Tensor + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(None), 0), paddle.assign(self.value) + ) + return x + def _get_answer(self): self.data[:, 0] = self.value @@ -994,6 +1272,10 @@ def set_shape(self): def _call_setitem(self, x): x[:, 0] = self.value # x is Paddle.Tensor + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(None), 0), self.value) + return x + def _get_answer(self): self.data[:, 0] = self.value @@ -1030,7 +1312,10 @@ def _value_type_error(self): ): x = paddle.ones(shape=self.shape, dtype=self.dtype) value = [1] - x[0] = value + if paddle.in_dynamic_mode(): + x[0] = value + else: + x = paddle.static.setitem(x, 0, value) def _dtype_error(self): with self.assertRaisesRegex( @@ -1043,7 +1328,10 @@ def _dtype_error(self): def _step_error(self): with self.assertRaisesRegex(ValueError, "step can not be 0"): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[0:1:0] = self.value + if paddle.in_dynamic_mode(): + x[0:1:0] = self.value + else: + x = paddle.static.setitem(x, slice(0, 1, 0), self.value) def _ellipsis_error(self): with self.assertRaisesRegex( @@ -1059,24 +1347,33 @@ def _ellipsis_error(self): def _bool_list_error(self): with self.assertRaises(TypeError): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[[True, False, 0]] = 0 + if paddle.in_dynamic_mode(): + x[[True, False, 0]] = 0 + else: + x = paddle.static.setitem(x, [True, False, 0], 0) with self.assertRaises(IndexError): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[[True, False], [True, False]] = 0 + if paddle.in_dynamic_mode(): + x[[True, False], [True, False]] = 0 + else: + x = paddle.static.setitem(x, ([True, False], [True, False]), 0) def _bool_tensor_error(self): with self.assertRaises(IndexError): x = paddle.ones(shape=self.shape, dtype=self.dtype) idx = paddle.assign([True, False, True]) - x[idx] = 0 + if paddle.in_dynamic_mode(): + x[idx] = 0 + else: + x = paddle.static.setitem(x, idx, 0) def _broadcast_mismatch(self): program = paddle.static.Program() with paddle.static.program_guard(program): x = paddle.ones(shape=self.shape, dtype=self.dtype) value = np.array([3, 4, 5, 6, 7]) - x[0] = value + x = paddle.static.setitem(x, 0, value) exe = paddle.static.Executor(paddle.CPUPlace()) with self.assertRaises(ValueError): exe.run(program) @@ -1104,7 +1401,10 @@ def forward(self, x, y): y = self.conv(y) var = y.flatten() - x[0, :, 0, 0] = var + if paddle.in_dynamic_mode(): + x[0, :, 0, 0] = var + else: + x = paddle.static.setitem(x, (0, slice(None), 0, 0), var) loss = paddle.mean(x) return loss, var, x @@ -1131,7 +1431,7 @@ def test_static(self): z = paddle.add(x, y) var = y[0, :] - z[0, :] = var + z = paddle.static.setitem(z, (0, slice(None)), var) prediction = paddle.static.nn.fc(x=z, size=2, activation='softmax') diff --git a/python/paddle/fluid/variable_index.py b/python/paddle/fluid/variable_index.py index 03ea61acb3e22..a4345caca19f5 100644 --- a/python/paddle/fluid/variable_index.py +++ b/python/paddle/fluid/variable_index.py @@ -858,10 +858,18 @@ def idx_not_empty(var, item, value): gather_val_new = value - gather_val out = scatter_nd_add(var, idx, gather_val_new) var = _setitem_impl_(var, ..., out) + return var + + def idx_is_empty(var): + return var from paddle.static.nn import cond # If all the bool index is False, just do nothing - cond(item.any(), lambda: idx_not_empty(var, item, value)) + var = cond( + item.any(), + lambda: idx_not_empty(var, item, value), + lambda: idx_is_empty(var), + ) return var From 825f058bcf657068f5778524bd8ba855599aeff8 Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Thu, 18 May 2023 02:48:46 +0000 Subject: [PATCH 11/26] fix unittests --- python/paddle/distribution/multinomial.py | 4 +++- .../fluid/tests/unittests/test_variable.py | 19 +++++++++---------- .../tests/unittests/test_zero_dim_tensor.py | 6 +++--- .../paddle/jit/dy2static/ast_transformer.py | 2 +- python/paddle/static/__init__.py | 1 - python/paddle/tensor/math.py | 14 +++++++++++--- test/dygraph_to_static/test_slice.py | 8 ++++++-- 7 files changed, 33 insertions(+), 21 deletions(-) diff --git a/python/paddle/distribution/multinomial.py b/python/paddle/distribution/multinomial.py index c57511da5c672..8b01a2fb85bf4 100644 --- a/python/paddle/distribution/multinomial.py +++ b/python/paddle/distribution/multinomial.py @@ -130,7 +130,9 @@ def log_prob(self, value): logits, value = paddle.broadcast_tensors( [paddle.log(self.probs), value] ) - logits[(value == 0) & (paddle.isinf(logits))] = 0 + logits = paddle.static.setitem( + logits, (value == 0) & (paddle.isinf(logits)), 0 + ) return ( paddle.lgamma(value.sum(-1) + 1) diff --git a/python/paddle/fluid/tests/unittests/test_variable.py b/python/paddle/fluid/tests/unittests/test_variable.py index cbac9dc1849e8..df3bc996a7f21 100644 --- a/python/paddle/fluid/tests/unittests/test_variable.py +++ b/python/paddle/fluid/tests/unittests/test_variable.py @@ -846,8 +846,7 @@ def run_setitem_list_index(self, array, index, value_np): name='value', shape=value_np.shape, dtype='float32' ) - x[index] = value - y = x + y = paddle.static.setitem(x, index, value) place = paddle.fluid.CPUPlace() prog = paddle.static.default_main_program() @@ -1046,8 +1045,8 @@ def test_static_graph_tensor_index_setitem_muti_dim(self): name='index_2', shape=index2.shape, dtype='int32' ) - x1[index_1, index_2] = value - x2[index_1] = value + x1_out = paddle.static.setitem(x1, (index_1, index_2), value) + x2_out = paddle.static.setitem(x2, index_1, value) place = ( paddle.fluid.CPUPlace() @@ -1059,7 +1058,7 @@ def test_static_graph_tensor_index_setitem_muti_dim(self): exe = paddle.static.Executor(place) exe.run(paddle.static.default_startup_program()) - fetch_list = [x1.name, x2.name] + fetch_list = [x1_out.name, x2_out.name] setitem_pp = exe.run( prog, @@ -1129,10 +1128,10 @@ def test_static_graph_array_index_muti_dim(self): name='x2', shape=array.shape, dtype='float32' ) - x1[index_mod1, index_mod2] = 1 - x2[index_mod1] = 2.5 - y1 = x1[index_mod2, index_mod1] - y2 = x2[index_mod2] + x1_out = paddle.static.setitem(x1, (index_mod1, index_mod2), 1) + x2_out = paddle.static.setitem(x2, index_mod1, 2.5) + y1 = x1_out[index_mod2, index_mod1] + y2 = x2_out[index_mod2] place = ( paddle.fluid.CPUPlace() if not paddle.fluid.core.is_compiled_with_cuda() @@ -1142,7 +1141,7 @@ def test_static_graph_array_index_muti_dim(self): prog = paddle.static.default_main_program() exe = paddle.static.Executor(place) exe.run(paddle.static.default_startup_program()) - fetch_list = [x1.name, x2.name, y1.name, y2.name] + fetch_list = [x1_out.name, x2_out.name, y1.name, y2.name] setitem_pp = exe.run( prog, 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 76f0ce1791a7b..b13ebf6d3165d 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2903,7 +2903,7 @@ def test_setitem(self): x = paddle.arange(2 * 3 * 4 * 5).reshape((2, 3, 4, 5)) x.stop_gradient = False out = x * 2 - out[1, 2, 3, 4] = 10 + out = paddle.static.setitem(out, (1, 2, 3, 4), 10) paddle.static.append_backward(out.sum()) prog = paddle.static.default_main_program() res = self.exe.run(prog, fetch_list=[out, x.grad_name]) @@ -2924,7 +2924,7 @@ def test_setitem(self): x.stop_gradient = False indice = paddle.full([], 1, dtype='int32') out = x * 1 - out[indice, indice] = 0.5 + out = paddle.static.setitem(out, (indice, indice), 0.5) paddle.static.append_backward(out.sum()) prog = paddle.static.default_main_program() res = self.exe.run(prog, fetch_list=[out, x.grad_name]) @@ -2943,7 +2943,7 @@ def test_setitem(self): v.stop_gradient = False indice = paddle.full([], 1, dtype='int32') out = x * 1 - out[indice] = v + out = paddle.static.setitem(out, indice, v) paddle.static.append_backward(out.sum()) prog = paddle.static.default_main_program() res = self.exe.run(prog, fetch_list=[out, x.grad_name, v.grad_name]) diff --git a/python/paddle/jit/dy2static/ast_transformer.py b/python/paddle/jit/dy2static/ast_transformer.py index bd2808c193494..cd9dbe391fc72 100644 --- a/python/paddle/jit/dy2static/ast_transformer.py +++ b/python/paddle/jit/dy2static/ast_transformer.py @@ -94,7 +94,6 @@ def transfer_from_node_type(self, node_wrapper): self.visit(node_wrapper.node) transformers = [ - SliceTransformer, RegisterHookTransformer, EarlyReturnTransformer, BasicApiTransformer, # Basic Api @@ -111,6 +110,7 @@ def transfer_from_node_type(self, node_wrapper): DecoratorTransformer, # transform decorators to function call NameloadJstTransformer, TypeHintTransformer, # remove all typehint in gast.Name + SliceTransformer, ] apply_optimization(transformers) diff --git a/python/paddle/static/__init__.py b/python/paddle/static/__init__.py index 9b10fbdcce76e..94b91db295cb9 100644 --- a/python/paddle/static/__init__.py +++ b/python/paddle/static/__init__.py @@ -127,5 +127,4 @@ 'set_ipu_shard', 'ctr_metric_bundle', 'exponential_decay', - 'setitem', ] diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index 40163ddf5d9d6..30600ed8e307c 100644 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -5542,10 +5542,18 @@ def vander(x, n=None, increasing=False, name=None): res = paddle.empty([x.shape[0], n], dtype=x.dtype) if n > 0: - res[:, 0] = paddle.to_tensor([1], dtype=x.dtype) + res = paddle.static.setitem( + res, (slice(None), 0), paddle.to_tensor([1], dtype=x.dtype) + ) if n > 1: - res[:, 1:] = x[:, None] - res[:, 1:] = paddle.cumprod(res[:, 1:], dim=-1) + res = paddle.static.setitem( + res, (slice(None), slice(1, None)), x[:, None] + ) + res = paddle.static.setitem( + res, + (slice(None), slice(1, None)), + paddle.cumprod(res[:, 1:], dim=-1), + ) res = res[:, ::-1] if not increasing else res return res diff --git a/test/dygraph_to_static/test_slice.py b/test/dygraph_to_static/test_slice.py index b4fd5f25d7ca8..59af18b706ce0 100644 --- a/test/dygraph_to_static/test_slice.py +++ b/test/dygraph_to_static/test_slice.py @@ -129,8 +129,12 @@ def run_dygraph_mode(self): return self._run(to_static=False) def _run(self, to_static): - paddle.jit.enable_to_static(to_static) - res = self.dygraph_func(self.input) + func = ( + paddle.jit.to_static(self.dygraph_func) + if to_static + else self.dygraph_func + ) + res = func(self.input) return res.numpy() def run_static_mode(self): From 3d60e1a4591dc763feb087bef7c8ee0f9fd90a18 Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Thu, 18 May 2023 09:08:44 +0000 Subject: [PATCH 12/26] [May case some error]: remove inplace-version check --- python/paddle/fluid/tests/unittests/test_var_base.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_var_base.py b/python/paddle/fluid/tests/unittests/test_var_base.py index 5fc9914fa1e88..295d14ca9d7b8 100644 --- a/python/paddle/fluid/tests/unittests/test_var_base.py +++ b/python/paddle/fluid/tests/unittests/test_var_base.py @@ -1365,12 +1365,10 @@ def set_dtype(self): def _test(self, value): paddle.disable_static() - self.assertEqual(self.tensor_x.inplace_version, 0) id_origin = id(self.tensor_x) index_1 = paddle.to_tensor(np.array([True, False, False, False])) self.tensor_x[index_1] = value - self.assertEqual(self.tensor_x.inplace_version, 1) if isinstance(value, (int, float)): result = np.zeros((2, 3)).astype(self.dtype) + value @@ -1383,13 +1381,11 @@ def _test(self, value): index_2 = paddle.to_tensor(np.array([False, True, False, False])) self.tensor_x[index_2] = value - self.assertEqual(self.tensor_x.inplace_version, 2) np.testing.assert_array_equal(self.tensor_x[1].numpy(), result) self.assertEqual(id_origin, id(self.tensor_x)) index_3 = paddle.to_tensor(np.array([True, True, True, True])) self.tensor_x[index_3] = value - self.assertEqual(self.tensor_x.inplace_version, 3) np.testing.assert_array_equal(self.tensor_x[3].numpy(), result) self.assertEqual(id_origin, id(self.tensor_x)) From 9b6d7779c27cff72f7cf541cae2b5386db48204c Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Thu, 18 May 2023 10:41:20 +0000 Subject: [PATCH 13/26] add two test case for dy2st --- test/dygraph_to_static/test_setitem.py | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py index 2bf8219028dbc..8b227688f2f23 100644 --- a/test/dygraph_to_static/test_setitem.py +++ b/test/dygraph_to_static/test_setitem.py @@ -149,5 +149,34 @@ def foo(x): return foo +class TestCase10(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[..., 4:6] = y[..., 4:6] * 10000 + return y + + return foo + + +class TestCase11(TestSetItemBase): + # Test gradient of value tensor + def init_func(self): + def foo(x, value): + y = x + 1 + y[2, 4] = value + return y + + return foo + + def run_dygrah(self, func): + x = self.init_data() + value = paddle.ones((16, 32)) + value.stop_gradient = False + y = func(x, value) + x_grad, value_grad = paddle.grad(y, [x, value]) + return y, x_grad, value_grad + + if __name__ == '__main__': unittest.main() From bb0c13ecf9fc8e3b69fcfa826ce617d9114d2fca Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Fri, 19 May 2023 08:57:24 +0000 Subject: [PATCH 14/26] fix function in vision --- .../vision/transforms/functional_tensor.py | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/python/paddle/vision/transforms/functional_tensor.py b/python/paddle/vision/transforms/functional_tensor.py index e2b7f3cc734d1..c4d0c2d04ce99 100644 --- a/python/paddle/vision/transforms/functional_tensor.py +++ b/python/paddle/vision/transforms/functional_tensor.py @@ -222,12 +222,12 @@ def _affine_grid(theta, w, h, ow, oh): base_grid = paddle.ones((1, oh, ow, 3), dtype=theta.dtype) x_grid = paddle.linspace(-ow * 0.5 + d, ow * 0.5 + d - 1, ow) - base_grid[..., 0] = x_grid if paddle.in_dynamic_mode(): y_grid = paddle.linspace( -oh * 0.5 + d, oh * 0.5 + d - 1, oh ).unsqueeze_(-1) + base_grid[..., 0] = x_grid base_grid[..., 1] = y_grid tmp = paddle.to_tensor([0.5 * w, 0.5 * h]) else: @@ -236,7 +236,8 @@ def _affine_grid(theta, w, h, ow, oh): y_grid = paddle.linspace(-oh * 0.5 + d, oh * 0.5 + d - 1, oh).unsqueeze( -1 ) - base_grid[..., 1] = y_grid + base_grid = paddle.static.setitem(base_grid, (..., 0), x_grid) + base_grid = paddle.static.setitem(base_grid, (..., 1), y_grid) tmp = paddle.assign(np.array([0.5 * w, 0.5 * h], dtype="float32")) scaled_theta = theta.transpose((0, 2, 1)) / tmp @@ -409,17 +410,23 @@ def rotate( paddle.zeros([1]), ] ) - - matrix[2] += matrix[0] * (-rotn_center[0] - post_trans[0]) + matrix[1] * ( - -rotn_center[1] - post_trans[1] + matrix = paddle.static.setitem( + matrix, + 2, + matrix[2] + + matrix[0] * (-rotn_center[0] - post_trans[0]) + + matrix[1] * (-rotn_center[1] - post_trans[1]) + + rotn_center[0], ) - matrix[5] += matrix[3] * (-rotn_center[0] - post_trans[0]) + matrix[4] * ( - -rotn_center[1] - post_trans[1] + matrix = paddle.static.setitem( + matrix, + 5, + matrix[5] + + matrix[3] * (-rotn_center[0] - post_trans[0]) + + matrix[4] * (-rotn_center[1] - post_trans[1]) + + rotn_center[1], ) - matrix[2] += rotn_center[0] - matrix[5] += rotn_center[1] - matrix = matrix.reshape((1, 2, 3)) if expand: @@ -621,7 +628,7 @@ def erase(img, i, j, h, w, v, inplace=False): if not inplace: img = img.clone() - img[..., i : i + h, j : j + w] = v + img = paddle.static.setitem(img, (..., slice(i, i + h), slice(j, j + w)), v) return img From f7e1641d681e3230453e70625db98608c4523e73 Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Fri, 26 May 2023 09:03:10 +0000 Subject: [PATCH 15/26] fix dy2st setitem support, refine UT case --- .../paddle/jit/dy2static/slice_transformer.py | 9 +++++++-- test/dygraph_to_static/test_setitem.py | 20 +++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/python/paddle/jit/dy2static/slice_transformer.py b/python/paddle/jit/dy2static/slice_transformer.py index a972df391c8cf..78ef13134d0d8 100644 --- a/python/paddle/jit/dy2static/slice_transformer.py +++ b/python/paddle/jit/dy2static/slice_transformer.py @@ -36,9 +36,14 @@ def __getitem__(self, item): def __setitem__(self, item, value): if isinstance(self.obj, Variable): - return paddle.fluid.framework._setitem_impl_(self.obj, item, value) + new_var = paddle.fluid.framework._setitem_impl_( + self.obj, item, value + ) + # NOTE(dev): Update __dict__ will not modify the id(), but only move the + # pointed reference object to the new one. + self.obj.__dict__.update(new_var.__dict__) elif hasattr(self.obj, '__setitem__'): - return self.obj.__setitem__(item, value) + self.obj.__setitem__(item, value) else: raise RuntimeError( "Unsupport _jst.GSet for {} because it has no __setitem__ method.".format( diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py index 8b227688f2f23..a21b63f8acb90 100644 --- a/test/dygraph_to_static/test_setitem.py +++ b/test/dygraph_to_static/test_setitem.py @@ -32,7 +32,7 @@ def init_data(self): def init_func(self): def foo(x): y = x + 1 - y[:, 2] = x[:, 2] + 1 + y[:, 2] = x[:, 2] + 100 return y return foo @@ -60,7 +60,7 @@ class TestCase1(TestSetItemBase): def init_func(self): def foo(x): y = x + 1 - y[2] = x[2] + 1 # (2, ) + y[2] = x[2] + 100 # (2, ) return y return foo @@ -70,7 +70,7 @@ class TestCase2(TestSetItemBase): def init_func(self): def foo(x): y = x + 1 - y[:] = x[:] + 1 # slice(None,None,None) + y[:] = x[:] + 100 # slice(None,None,None) return y return foo @@ -80,7 +80,7 @@ class TestCase3(TestSetItemBase): def init_func(self): def foo(x): y = x + 1 - y[1::2] = x[1::2] + 1 # slice(1,None,2) + y[1::2] = x[1::2] + 100 # slice(1,None,2) return y return foo @@ -90,7 +90,7 @@ class TestCase4(TestSetItemBase): def init_func(self): def foo(x): y = x + 1 - y[1, 2] = x[1, 2] + 1 # (1, 2) + y[1, 2] = x[1, 2] + 100 # (1, 2) return y return foo @@ -100,7 +100,7 @@ class TestCase5(TestSetItemBase): def init_func(self): def foo(x): y = x + 1 - y[[1, 2], [2, 3]] = x[[1, 2], [2, 3]] + 1 # ([1,2],[2,3]) + y[[1, 2], [2, 3]] = x[[1, 2], [2, 3]] + 100 # ([1,2],[2,3]) return y return foo @@ -110,7 +110,7 @@ class TestCase6(TestSetItemBase): def init_func(self): def foo(x): y = x + 1 - y[1, :, 3] = x[1, :, 3] + 1 # slice(None,None,None),3) + y[1, :, 3] = x[1, :, 3] + 100 # slice(None,None,None),3) return y return foo @@ -120,7 +120,7 @@ class TestCase7(TestSetItemBase): def init_func(self): def foo(x): y = x + 1 - y[1, ..., 2] = x[1, ..., 2] + 1 # (1, ..., 2) + y[1, ..., 2] = x[1, ..., 2] + 100 # (1, ..., 2) return y return foo @@ -131,7 +131,7 @@ def init_func(self): def foo(x): y = x + 1 index = paddle.to_tensor([1, 2], dtype="int64") - y[index] = x[index] + 1 # Tensor([1,2]) + y[index] = x[index] + 100 # Tensor([1,2]) return y return foo @@ -143,7 +143,7 @@ def foo(x): y = x + 1 one = paddle.to_tensor(1, dtype="int64") two = paddle.to_tensor(2, dtype="int64") - y[one, :, :, 2] = x[1, :, :, two] + 1 # Tensor(1), Tensor(2) + y[one, :, :, 2] = x[1, :, :, two] + 100 # Tensor(1), Tensor(2) return y return foo From 51345e196c83b673aab5082aa383a03bf675f780 Mon Sep 17 00:00:00 2001 From: NotHaozi Date: Mon, 10 Jul 2023 07:32:08 +0000 Subject: [PATCH 16/26] fix slice in static_mode --- python/paddle/fluid/variable_index.py | 14 +- .../paddle/jit/dy2static/convert_operators.py | 6 + test/dygraph_to_static/test_setitem.py | 153 ++++++++++++++++++ 3 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 test/dygraph_to_static/test_setitem.py diff --git a/python/paddle/fluid/variable_index.py b/python/paddle/fluid/variable_index.py index 4f7c94a5acb85..8aa4072bf4f5d 100644 --- a/python/paddle/fluid/variable_index.py +++ b/python/paddle/fluid/variable_index.py @@ -21,6 +21,9 @@ MAX_INTEGER = 2**31 - 1 +# map var to the new output +var_dict = {} + def is_list_tuple(index, contain_type): def _is_list_tuple(item): @@ -807,17 +810,24 @@ def _setitem_impl_(var, item, value): if paddle.in_dynamic_mode(): var._bump_inplace_version() + output = var + else: + helper = paddle.fluid.layer_helper.LayerHelper('set_value', **locals()) + output = helper.create_variable_for_type_inference(dtype=var.dtype) cur_block = default_main_program().current_block() cur_block.append_op( type="set_value", inputs=inputs, - outputs={'Out': var}, + outputs={'Out': output}, attrs=attrs, inplace_map={"Input": "Out"}, ) - return var + # map var to the new output + var_dict[var.desc.id()] = output + + return output # the item is a tensor of bool diff --git a/python/paddle/jit/dy2static/convert_operators.py b/python/paddle/jit/dy2static/convert_operators.py index 39029708320a3..e8462de6f655c 100644 --- a/python/paddle/jit/dy2static/convert_operators.py +++ b/python/paddle/jit/dy2static/convert_operators.py @@ -23,6 +23,7 @@ from paddle.fluid.framework import Variable, core from paddle.fluid.layers import control_flow from paddle.fluid.layers.control_flow import while_loop +from paddle.fluid.variable_index import var_dict from .utils import ( RETURN_NO_VALUE_VAR_NAME, @@ -48,6 +49,11 @@ def convert_load(x): TODO:(@xiongkun) may run convert_load in dygraph mode, which should be fixed. """ return _convert_into_variable(x) + + # map var to the new output + if isinstance(x, paddle.fluid.framework.Variable): + if x.desc.id() in var_dict.keys(): + return var_dict[x.desc.id()] return x diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py new file mode 100644 index 0000000000000..cc8fbbff2bb24 --- /dev/null +++ b/test/dygraph_to_static/test_setitem.py @@ -0,0 +1,153 @@ +# Copyright (c) 2023 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. + +import unittest + +import numpy as np + +import paddle + + +class TestSetItemBase(unittest.TestCase): + def setUp(self) -> None: + pass + + def init_data(self): + paddle.seed(2023) + x = paddle.randn([4, 8, 16, 32]) + x.stop_gradient = False + return x + + def init_func(self): + def foo(x): + y = x + 1 + y[:, 2] = x[:, 2] + 1 + return y + + return foo + + def test_case(self): + func = self.init_func() + dy_res = self.run_dygrah(func) + st_res = self.run_to_static(func) + + for dy_out, st_out in zip(dy_res, st_res): + np.testing.assert_allclose(dy_out.numpy(), st_out.numpy()) + + def run_dygrah(self, func): + x = self.init_data() + y = func(x) + x_grad = paddle.grad(y, x)[0] + return y, x_grad + + def run_to_static(self, func): + func = paddle.jit.to_static(func) + return self.run_dygrah(func) + + +class TestCase1(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[2] = x[2] + 1 # (2, ) + return y + + return foo + + +class TestCase2(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[:] = x[:] + 1 # slice(None,None,None) + return y + + return foo + + +class TestCase3(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[1::2] = x[1::2] + 1 # slice(1,None,2) + return y + + return foo + + +class TestCase4(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[1, 2] = x[1, 2] + 1 # (1, 2) + return y + + return foo + + +class TestCase5(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[[1, 2], [2, 3]] = x[[1, 2], [2, 3]] + 1 # ([1,2],[2,3]) + return y + + return foo + + +class TestCase6(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[1, :, 3] = x[1, :, 3] + 1 # slice(None,None,None),3) + return y + + return foo + + +class TestCase7(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + y[1, ..., 2] = x[1, ..., 2] + 1 # (1, ..., 2) + return y + + return foo + + +class TestCase8(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + index = paddle.to_tensor([1, 2], dtype="int64") + y[index] = x[index] + 1 # Tensor([1,2]) + return y + + return foo + + +class TestCase9(TestSetItemBase): + def init_func(self): + def foo(x): + y = x + 1 + one = paddle.to_tensor([1], dtype="int64") + two = paddle.to_tensor([2], dtype="int64") + y[one, :, :, 2] = x[1, :, :, two] + 1 # Tensor([1]), Tensor([2]) + return y + + return foo + + +if __name__ == '__main__': + unittest.main() From dfd777f475ab05e19219c9bf7658dce60415232e Mon Sep 17 00:00:00 2001 From: NotHaozi Date: Mon, 10 Jul 2023 10:24:24 +0000 Subject: [PATCH 17/26] add ParametersMap --- python/paddle/fluid/variable_index.py | 11 +++-- .../paddle/jit/dy2static/convert_operators.py | 19 +++++--- .../jit/dy2static/program_translator.py | 38 ++++++++++++++++ test/dygraph_to_static/test_setitem.py | 44 +++++++++---------- 4 files changed, 80 insertions(+), 32 deletions(-) diff --git a/python/paddle/fluid/variable_index.py b/python/paddle/fluid/variable_index.py index 8aa4072bf4f5d..47e1627447559 100644 --- a/python/paddle/fluid/variable_index.py +++ b/python/paddle/fluid/variable_index.py @@ -21,9 +21,6 @@ MAX_INTEGER = 2**31 - 1 -# map var to the new output -var_dict = {} - def is_list_tuple(index, contain_type): def _is_list_tuple(item): @@ -825,7 +822,13 @@ def _setitem_impl_(var, item, value): ) # map var to the new output - var_dict[var.desc.id()] = output + from paddle.jit.dy2static.program_translator import ( + ProgramTranslator, + ) + + ProgramTranslator.get_instance()._params_map.add( + cur_block.program, var.desc.id(), output + ) return output diff --git a/python/paddle/jit/dy2static/convert_operators.py b/python/paddle/jit/dy2static/convert_operators.py index e8462de6f655c..7d35f2c8eb076 100644 --- a/python/paddle/jit/dy2static/convert_operators.py +++ b/python/paddle/jit/dy2static/convert_operators.py @@ -20,10 +20,9 @@ _convert_into_variable, in_declarative_mode, ) -from paddle.fluid.framework import Variable, core +from paddle.fluid.framework import Variable, core, default_main_program from paddle.fluid.layers import control_flow from paddle.fluid.layers.control_flow import while_loop -from paddle.fluid.variable_index import var_dict from .utils import ( RETURN_NO_VALUE_VAR_NAME, @@ -50,10 +49,18 @@ def convert_load(x): """ return _convert_into_variable(x) - # map var to the new output - if isinstance(x, paddle.fluid.framework.Variable): - if x.desc.id() in var_dict.keys(): - return var_dict[x.desc.id()] + # get the new output of the var + if isinstance(x, Variable): + cur_block = default_main_program().current_block() + + from paddle.jit.dy2static.program_translator import ProgramTranslator + + new_var = ProgramTranslator.get_instance()._params_map.get( + cur_block.program, x.desc.id() + ) + if new_var is not None: + return new_var + return x diff --git a/python/paddle/jit/dy2static/program_translator.py b/python/paddle/jit/dy2static/program_translator.py index c0ea50e1e263f..d00207f10a31f 100644 --- a/python/paddle/jit/dy2static/program_translator.py +++ b/python/paddle/jit/dy2static/program_translator.py @@ -1125,6 +1125,43 @@ def _program_hash(self, program): return id(program) +class ParametersMap: + def __init__(self): + self.params_dict = {} + + @synchronized + def add(self, program, id, param): + """use the default_program as key, append param the parameter list.""" + key = self._program_hash(program) + if key not in self.params_dict: + self.params_dict[key] = {} + + params = self.params_dict[key] + params[id] = param + + def get(self, program, id): + params = self.params_dict.get(self._program_hash(program)) + if params is None: + return None + if id in params.keys(): + return params[id] + return None + + def pop(self, program): + params = self.params_dict.get(self._program_hash(program)) + if params is None: + return [] + del self.params_dict[self._program_hash(program)] + return list(params) + + def _program_hash(self, program): + """ + because program is not deleted while calling from_func_spec. + so it's ok to use id(program) + """ + return id(program) + + class FallbackProgramLayer: __slots__ = [ '_instance', @@ -1386,6 +1423,7 @@ def __init__(self): self._initialized = True self._program_cache = ProgramCache() self._params_recorder = ParametersRecorder() + self._params_map = ParametersMap() self.enable_to_static = True def enable(self, enable_to_static): diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py index cc8fbbff2bb24..7db73053cd6ce 100644 --- a/test/dygraph_to_static/test_setitem.py +++ b/test/dygraph_to_static/test_setitem.py @@ -31,8 +31,8 @@ def init_data(self): def init_func(self): def foo(x): - y = x + 1 - y[:, 2] = x[:, 2] + 1 + y = x + 99 + y[:, 2] = x[:, 2] + 99 return y return foo @@ -59,8 +59,8 @@ def run_to_static(self, func): class TestCase1(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 - y[2] = x[2] + 1 # (2, ) + y = x + 99 + y[2] = x[2] + 99 # (2, ) return y return foo @@ -69,8 +69,8 @@ def foo(x): class TestCase2(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 - y[:] = x[:] + 1 # slice(None,None,None) + y = x + 99 + y[:] = x[:] + 99 # slice(None,None,None) return y return foo @@ -79,8 +79,8 @@ def foo(x): class TestCase3(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 - y[1::2] = x[1::2] + 1 # slice(1,None,2) + y = x + 99 + y[1::2] = x[1::2] + 99 # slice(1,None,2) return y return foo @@ -89,8 +89,8 @@ def foo(x): class TestCase4(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 - y[1, 2] = x[1, 2] + 1 # (1, 2) + y = x + 99 + y[1, 2] = x[1, 2] + 99 # (1, 2) return y return foo @@ -99,8 +99,8 @@ def foo(x): class TestCase5(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 - y[[1, 2], [2, 3]] = x[[1, 2], [2, 3]] + 1 # ([1,2],[2,3]) + y = x + 99 + y[[1, 2], [2, 3]] = x[[1, 2], [2, 3]] + 99 # ([1,2],[2,3]) return y return foo @@ -109,8 +109,8 @@ def foo(x): class TestCase6(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 - y[1, :, 3] = x[1, :, 3] + 1 # slice(None,None,None),3) + y = x + 99 + y[1, :, 3] = x[1, :, 3] + 99 # slice(None,None,None),3) return y return foo @@ -119,8 +119,8 @@ def foo(x): class TestCase7(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 - y[1, ..., 2] = x[1, ..., 2] + 1 # (1, ..., 2) + y = x + 99 + y[1, ..., 2] = x[1, ..., 2] + 99 # (1, ..., 2) return y return foo @@ -129,9 +129,9 @@ def foo(x): class TestCase8(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 + y = x + 99 index = paddle.to_tensor([1, 2], dtype="int64") - y[index] = x[index] + 1 # Tensor([1,2]) + y[index] = x[index] + 99 # Tensor([1,2]) return y return foo @@ -140,10 +140,10 @@ def foo(x): class TestCase9(TestSetItemBase): def init_func(self): def foo(x): - y = x + 1 - one = paddle.to_tensor([1], dtype="int64") - two = paddle.to_tensor([2], dtype="int64") - y[one, :, :, 2] = x[1, :, :, two] + 1 # Tensor([1]), Tensor([2]) + y = x + 99 + one = paddle.to_tensor(1, dtype="int64") + two = paddle.to_tensor(2, dtype="int64") + y[one, :, :, 2] = x[1, :, :, two] + 99 # Tensor([1]), Tensor([2]) return y return foo From 8d8eb6a4131dfcc0026e7a0d8d758a8461dcdf04 Mon Sep 17 00:00:00 2001 From: NotHaozi Date: Mon, 10 Jul 2023 11:48:44 +0000 Subject: [PATCH 18/26] remove pop --- python/paddle/jit/dy2static/program_translator.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/python/paddle/jit/dy2static/program_translator.py b/python/paddle/jit/dy2static/program_translator.py index d00207f10a31f..db612474c87d2 100644 --- a/python/paddle/jit/dy2static/program_translator.py +++ b/python/paddle/jit/dy2static/program_translator.py @@ -1147,13 +1147,6 @@ def get(self, program, id): return params[id] return None - def pop(self, program): - params = self.params_dict.get(self._program_hash(program)) - if params is None: - return [] - del self.params_dict[self._program_hash(program)] - return list(params) - def _program_hash(self, program): """ because program is not deleted while calling from_func_spec. From e8ecda11f9a71524db1d97dc02554a4342545032 Mon Sep 17 00:00:00 2001 From: NotHaozi Date: Tue, 11 Jul 2023 02:30:03 +0000 Subject: [PATCH 19/26] modify place --- python/paddle/fluid/variable_index.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/python/paddle/fluid/variable_index.py b/python/paddle/fluid/variable_index.py index 47e1627447559..a39b05d5c0aa0 100644 --- a/python/paddle/fluid/variable_index.py +++ b/python/paddle/fluid/variable_index.py @@ -821,14 +821,15 @@ def _setitem_impl_(var, item, value): inplace_map={"Input": "Out"}, ) - # map var to the new output - from paddle.jit.dy2static.program_translator import ( - ProgramTranslator, - ) + if not paddle.in_dynamic_mode(): + # map var to the new output + from paddle.jit.dy2static.program_translator import ( + ProgramTranslator, + ) - ProgramTranslator.get_instance()._params_map.add( - cur_block.program, var.desc.id(), output - ) + ProgramTranslator.get_instance()._params_map.add( + cur_block.program, var.desc.id(), output + ) return output From df0debcb904c032e40c82867f2cbd5f9163c3969 Mon Sep 17 00:00:00 2001 From: NotHaozi Date: Tue, 11 Jul 2023 02:52:11 +0000 Subject: [PATCH 20/26] [fix]: variable is also a tensor --- .../paddle/jit/dy2static/convert_operators.py | 2 +- test/dygraph_to_static/test_setitem.py | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/python/paddle/jit/dy2static/convert_operators.py b/python/paddle/jit/dy2static/convert_operators.py index 7d35f2c8eb076..b1823785cda5c 100644 --- a/python/paddle/jit/dy2static/convert_operators.py +++ b/python/paddle/jit/dy2static/convert_operators.py @@ -50,7 +50,7 @@ def convert_load(x): return _convert_into_variable(x) # get the new output of the var - if isinstance(x, Variable): + if in_declarative_mode() and isinstance(x, Variable): cur_block = default_main_program().current_block() from paddle.jit.dy2static.program_translator import ProgramTranslator diff --git a/test/dygraph_to_static/test_setitem.py b/test/dygraph_to_static/test_setitem.py index 7db73053cd6ce..581d336614a90 100644 --- a/test/dygraph_to_static/test_setitem.py +++ b/test/dygraph_to_static/test_setitem.py @@ -31,7 +31,7 @@ def init_data(self): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 y[:, 2] = x[:, 2] + 99 return y @@ -59,7 +59,7 @@ def run_to_static(self, func): class TestCase1(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 y[2] = x[2] + 99 # (2, ) return y @@ -69,7 +69,7 @@ def foo(x): class TestCase2(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 y[:] = x[:] + 99 # slice(None,None,None) return y @@ -79,7 +79,7 @@ def foo(x): class TestCase3(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 y[1::2] = x[1::2] + 99 # slice(1,None,2) return y @@ -89,7 +89,7 @@ def foo(x): class TestCase4(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 y[1, 2] = x[1, 2] + 99 # (1, 2) return y @@ -99,7 +99,7 @@ def foo(x): class TestCase5(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 y[[1, 2], [2, 3]] = x[[1, 2], [2, 3]] + 99 # ([1,2],[2,3]) return y @@ -109,7 +109,7 @@ def foo(x): class TestCase6(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 y[1, :, 3] = x[1, :, 3] + 99 # slice(None,None,None),3) return y @@ -119,7 +119,7 @@ def foo(x): class TestCase7(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 y[1, ..., 2] = x[1, ..., 2] + 99 # (1, ..., 2) return y @@ -129,7 +129,7 @@ def foo(x): class TestCase8(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 index = paddle.to_tensor([1, 2], dtype="int64") y[index] = x[index] + 99 # Tensor([1,2]) return y @@ -140,7 +140,7 @@ def foo(x): class TestCase9(TestSetItemBase): def init_func(self): def foo(x): - y = x + 99 + y = x + 1 one = paddle.to_tensor(1, dtype="int64") two = paddle.to_tensor(2, dtype="int64") y[one, :, :, 2] = x[1, :, :, two] + 99 # Tensor([1]), Tensor([2]) From 3013d67873733f49aa56db47b53551c46ce282e2 Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Tue, 11 Jul 2023 07:37:26 +0000 Subject: [PATCH 21/26] rewrite some ut & remove slicetransformer in dy2st --- python/paddle/jit/dy2static/__init__.py | 1 - .../paddle/jit/dy2static/slice_transformer.py | 78 ---- test/legacy_test/test_set_value_op.py | 350 ++++++++++++++++-- test/legacy_test/test_variable.py | 20 +- test/legacy_test/test_zero_dim_tensor.py | 6 +- 5 files changed, 336 insertions(+), 119 deletions(-) delete mode 100644 python/paddle/jit/dy2static/slice_transformer.py diff --git a/python/paddle/jit/dy2static/__init__.py b/python/paddle/jit/dy2static/__init__.py index 1c505b2cf2bc9..136ab6dab7d40 100644 --- a/python/paddle/jit/dy2static/__init__.py +++ b/python/paddle/jit/dy2static/__init__.py @@ -32,7 +32,6 @@ from .variable_trans_func import to_static_variable # noqa: F401 from .convert_operators import convert_shape_compare # noqa: F401 from .assert_transformer import AssertTransformer -from .slice_transformer import GetSetter as GSet # noqa: F401 from .ast_transformer import DygraphToStaticAst from .program_translator import convert_to_static from .static_analysis import NodeVarType, StaticAnalysisVisitor diff --git a/python/paddle/jit/dy2static/slice_transformer.py b/python/paddle/jit/dy2static/slice_transformer.py deleted file mode 100644 index 78ef13134d0d8..0000000000000 --- a/python/paddle/jit/dy2static/slice_transformer.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2023 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. - -import paddle -from paddle.fluid.framework import Variable - -from .base_transformer import BaseTransformer -from .static_analysis import AstNodeWrapper -from .utils import ast_to_source_code, gast - -__all__ = [] - - -class GetSetter: - """ - GetSetter is a Proxy class implenenting Python getter / setter magic method. It's basic unit - for _jst.GSet(...) to make us not care what ast is like. - """ - - def __init__(self, obj): - self.obj = obj - - def __getitem__(self, item): - return self.obj[item] - - def __setitem__(self, item, value): - if isinstance(self.obj, Variable): - new_var = paddle.fluid.framework._setitem_impl_( - self.obj, item, value - ) - # NOTE(dev): Update __dict__ will not modify the id(), but only move the - # pointed reference object to the new one. - self.obj.__dict__.update(new_var.__dict__) - elif hasattr(self.obj, '__setitem__'): - self.obj.__setitem__(item, value) - else: - raise RuntimeError( - "Unsupport _jst.GSet for {} because it has no __setitem__ method.".format( - self.obj - ) - ) - - -class SliceTransformer(BaseTransformer): - """ - This calss transforms Expr[...] = Expr into _jst.GSet(Expr)[...] = Expr. - """ - - def __init__(self, wrapper_root): - assert isinstance( - wrapper_root, AstNodeWrapper - ), "Input non-AstNodeWrapper node for the initialization of CallTransformer." - self.wrapper_root = wrapper_root - self.root = wrapper_root.node - - def transform(self): - self.visit(self.root) - - def visit_Subscript(self, node): - self.generic_visit(node) - - value = ast_to_source_code(node.value).strip() - new_value_str = f"_jst.GSet({value})" - new_value_node = gast.parse(new_value_str).body[0].value - node.value = new_value_node - - return node diff --git a/test/legacy_test/test_set_value_op.py b/test/legacy_test/test_set_value_op.py index c87d5fd4729e5..bc6e1903af3b0 100644 --- a/test/legacy_test/test_set_value_op.py +++ b/test/legacy_test/test_set_value_op.py @@ -46,6 +46,10 @@ def set_dtype(self): def _call_setitem(self, x): x[0, 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, 0), self.value) + return x + def _get_answer(self): self.data[0, 0] = self.value @@ -55,7 +59,7 @@ def _run_static(self): paddle.enable_static() with paddle.static.program_guard(self.program): x = paddle.ones(shape=self.shape, dtype=self.dtype) - self._call_setitem(x) + x = self._call_setitem_static_api(x) exe = paddle.static.Executor(paddle.CPUPlace()) out = exe.run(self.program, fetch_list=[x]) @@ -94,6 +98,10 @@ class TestSetValueItemInt(TestSetValueApi): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -104,6 +112,10 @@ class TestSetValueItemSlice(TestSetValueApi): def _call_setitem(self, x): x[0:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 2), self.value) + return x + def _get_answer(self): self.data[0:2] = self.value @@ -112,6 +124,10 @@ class TestSetValueItemSlice2(TestSetValueApi): def _call_setitem(self, x): x[0:-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, -1), self.value) + return x + def _get_answer(self): self.data[0:-1] = self.value @@ -120,6 +136,10 @@ class TestSetValueItemSlice3(TestSetValueApi): def _call_setitem(self, x): x[0:-1, 0:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(0, -1), slice(0, 2)), self.value) + return + def _get_answer(self): self.data[0:-1, 0:2] = self.value @@ -128,6 +148,12 @@ class TestSetValueItemSlice4(TestSetValueApi): def _call_setitem(self, x): x[0:, 1:2, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), slice(1, 2), slice(None)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:2, :] = self.value @@ -136,6 +162,12 @@ class TestSetValueItemSlice5(TestSetValueApi): def _call_setitem(self, x): x[0:, 1:1, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), slice(1, 1), slice(None)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:1, :] = self.value @@ -153,6 +185,19 @@ def body(i, x): i = paddle.zeros(shape=(1,), dtype='int32') i, x = paddle.static.nn.while_loop(cond, body, [i, x]) + def _call_setitem_static_api(self, x): + def cond(i, x): + return i < 1 + + def body(i, x): + x = paddle.static.setitem(x, i, self.value) + i = i + 1 + return i, x + + i = paddle.zeros(shape=(1,), dtype='int32') + i, x = paddle.static.nn.while_loop(cond, body, [i, x]) + return x + def _get_answer(self): self.data[0] = self.value @@ -165,6 +210,10 @@ def set_shape(self): def _call_setitem(self, x): x[0:2:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 2, 2), self.value) + return x + def _get_answer(self): self.data[0:2:2] = self.value @@ -176,6 +225,10 @@ def set_shape(self): def _call_setitem(self, x): x[0:-1:3] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, -1, 3), self.value) + return x + def _get_answer(self): self.data[0:-1:3] = self.value @@ -184,6 +237,12 @@ class TestSetValueItemSliceStep3(TestSetValueApi): def _call_setitem(self, x): x[0:-1, 0:2, ::2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, -1), slice(0, 2), slice(None, None, 2)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2, ::2] = self.value @@ -192,6 +251,12 @@ class TestSetValueItemSliceStep4(TestSetValueApi): def _call_setitem(self, x): x[0:, 1:2:2, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), slice(1, 2, 2), slice(None)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:2:2, :] = self.value @@ -207,6 +272,10 @@ def set_value(self): def _call_setitem(self, x): x[5:2:-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(5, 2, -1), self.value) + return x + def _get_answer(self): self.data[5:2:-1] = self.value @@ -221,6 +290,10 @@ def set_value(self): def _call_setitem(self, x): x[1::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(1, None, -1), self.value) + return x + def _get_answer(self): self.data[1::-1] = self.value @@ -235,6 +308,10 @@ def set_value(self): def _call_setitem(self, x): x[::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(None, None, -1), self.value) + return x + def _get_answer(self): self.data[::-1] = self.value @@ -246,6 +323,12 @@ def set_shape(self): def _call_setitem(self, x): x[2:0:-1, 0:2, ::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(2, 0, -1), slice(0, 2), slice(None, None, -1)), self.value + ) + return x + def _get_answer(self): self.data[2:0:-1, 0:2, ::-1] = self.value @@ -257,6 +340,12 @@ class TestSetValueItemEllipsis1(TestSetValueApi): def _call_setitem(self, x): x[0:, ..., 1:] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), ..., slice(1, None)), self.value + ) + return x + def _get_answer(self): self.data[0:, ..., 1:] = self.value @@ -265,6 +354,10 @@ class TestSetValueItemEllipsis2(TestSetValueApi): def _call_setitem(self, x): x[0:, ...] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(0, None), ...), self.value) + return x + def _get_answer(self): self.data[0:, ...] = self.value @@ -273,6 +366,10 @@ class TestSetValueItemEllipsis3(TestSetValueApi): def _call_setitem(self, x): x[..., 1:] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (..., slice(1, None)), self.value) + return x + def _get_answer(self): self.data[..., 1:] = self.value @@ -281,6 +378,10 @@ class TestSetValueItemEllipsis4(TestSetValueApi): def _call_setitem(self, x): x[...] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, ..., self.value) + return x + def _get_answer(self): self.data[...] = self.value @@ -288,49 +389,84 @@ def _get_answer(self): # 1.4 item is Paddle Tensor class TestSetValueItemTensor(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") + zero = paddle.full([], 0, dtype="int32") x[zero] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + x = paddle.static.setitem(x, zero, self.value) + return x + def _get_answer(self): self.data[0] = self.value class TestSetValueItemTensor2(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") - two = paddle.full([1], 2, dtype="int64") + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") x[zero:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") + x = paddle.static.setitem(x, slice(zero, two), self.value) + return x + def _get_answer(self): self.data[0:2] = self.value class TestSetValueItemTensor3(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") - two = paddle.full([1], 2, dtype="int64") + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") x[zero:-1, 0:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") + x = paddle.static.setitem( + x, (slice(zero, -1), slice(0, two)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2] = self.value class TestSetValueItemTensor4(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") - two = paddle.full([1], 2, dtype="int64") + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") x[0:-1, zero:2, 0:6:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") + x = paddle.static.setitem( + x, (slice(0, -1), slice(zero, 2), slice(0, 6, two)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2, ::2] = self.value class TestSetValueItemTensor5(TestSetValueApi): def _call_setitem(self, x): - zero = paddle.full([1], 0, dtype="int32") - two = paddle.full([1], 2, dtype="int64") + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") x[zero:, 1:2:two, :] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([], 0, dtype="int32") + two = paddle.full([], 2, dtype="int64") + x = paddle.static.setitem( + x, (slice(zero, None), slice(1, 2, two)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:2:2, :] = self.value @@ -340,10 +476,20 @@ def set_shape(self): self.shape = [3, 4, 5] def _call_setitem(self, x): - minus1 = paddle.full([1], -1, dtype="int32") - zero = paddle.full([1], 0, dtype="int32") + minus1 = paddle.full([], -1, dtype="int32") + zero = paddle.full([], 0, dtype="int32") x[2:zero:minus1, 0:2, 10:-6:minus1] = self.value + def _call_setitem_static_api(self, x): + minus1 = paddle.full([], -1, dtype="int32") + zero = paddle.full([], 0, dtype="int64") + x = paddle.static.setitem( + x, + (slice(2, zero, minus1), slice(0, 2), slice(10, -6, minus1)), + self.value, + ) + return x + def _get_answer(self): self.data[2:0:-1, 0:2, ::-1] = self.value @@ -353,6 +499,10 @@ class TestSetValueItemNone1(TestSetValueApi): def _call_setitem(self, x): x[None] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, None, self.value) + return x + def _get_answer(self): self.data[None] = self.value @@ -361,6 +511,10 @@ class TestSetValueItemNone2(TestSetValueApi): def _call_setitem(self, x): x[0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, None, 1] = self.value @@ -369,6 +523,10 @@ class TestSetValueItemNone3(TestSetValueApi): def _call_setitem(self, x): x[:, None, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(None), None, None, 1), self.value) + return x + def _get_answer(self): self.data[:, None, None, 1] = self.value @@ -377,6 +535,10 @@ class TestSetValueItemNone4(TestSetValueApi): def _call_setitem(self, x): x[0, 0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, 0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, 0, None, 1] = self.value @@ -385,6 +547,10 @@ class TestSetValueItemNone5(TestSetValueApi): def _call_setitem(self, x): x[0, None, 0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, None, 0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, None, 0, None, 1] = self.value @@ -393,6 +559,10 @@ class TestSetValueItemNone6(TestSetValueApi): def _call_setitem(self, x): x[None, 0, 0, None, 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (None, 0, 0, None, 0), self.value) + return x + def _get_answer(self): self.data[None, 0, 0, None, 0] = self.value @@ -401,6 +571,12 @@ class TestSetValueItemNone7(TestSetValueApi): def _call_setitem(self, x): x[:, None, 1] = np.zeros(self.shape)[:, None, 0] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(None), None, 1), np.zeros(self.shape)[:, None, 0] + ) + return x + def _get_answer(self): self.data[:, None, 1] = np.zeros(self.shape)[:, None, 0] @@ -409,6 +585,12 @@ class TestSetValueItemNone8(TestSetValueApi): def _call_setitem(self, x): x[:, 1, None] = np.zeros(self.shape)[:, 0, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(None), 1, None), np.zeros(self.shape)[:, 0, None] + ) + return x + def _get_answer(self): self.data[:, 1, None] = np.zeros(self.shape)[:, 0, None] @@ -417,6 +599,14 @@ class TestSetValueItemNone9(TestSetValueApi): def _call_setitem(self, x): x[None, :, 1, ..., None] = np.zeros(self.shape)[0, 0, :, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (None, slice(None), 1, ..., None), + np.zeros(self.shape)[0, 0, :, None], + ) + return x + def _get_answer(self): self.data[None, :, 1, ..., None] = np.zeros(self.shape)[0, 0, :, None] @@ -425,15 +615,29 @@ class TestSetValueItemNone10(TestSetValueApi): def _call_setitem(self, x): x[..., None, :, None] = np.zeros(self.shape)[..., None, :, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (..., None, slice(None), None), + np.zeros(self.shape)[..., None, :, None], + ) + return x + def _get_answer(self): self.data[..., None, :, None] = np.zeros(self.shape)[..., None, :, None] -# 1.5 item is list or Tensor of bol +# 1.5 item is list or Tensor of bool +# NOTE(zoooo0820): Currently, 1-D List is same to Tuple. +# The semantic of index will be modified later. class TestSetValueItemBool1(TestSetValueApi): def _call_setitem(self, x): x[[True, False]] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [True, False], self.value) + return x + def _get_answer(self): self.data[[True, False]] = self.value @@ -442,6 +646,10 @@ class TestSetValueItemBool2(TestSetValueApi): def _call_setitem(self, x): x[[False, False]] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [False, False], self.value) + return x + def _get_answer(self): self.data[[False, False]] = self.value @@ -450,6 +658,10 @@ class TestSetValueItemBool3(TestSetValueApi): def _call_setitem(self, x): x[[False, True]] = np.zeros(self.shape[2]) + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [False, True], np.zeros(self.shape[2])) + return x + def _get_answer(self): self.data[[False, True]] = np.zeros(self.shape[2]) @@ -459,6 +671,11 @@ def _call_setitem(self, x): idx = paddle.assign(np.array([False, True])) x[idx] = np.zeros(self.shape[2]) + def _call_setitem_static_api(self, x): + idx = paddle.assign(np.array([False, True])) + x = paddle.static.setitem(x, idx, np.zeros(self.shape[2])) + return x + def _get_answer(self): self.data[np.array([False, True])] = np.zeros(self.shape[2]) @@ -470,6 +687,13 @@ def _call_setitem(self, x): ) x[idx] = self.value + def _call_setitem_static_api(self, x): + idx = paddle.assign( + np.array([[False, True, False], [True, True, False]]) + ) + x = paddle.static.setitem(x, idx, self.value) + return x + def _get_answer(self): self.data[ np.array([[False, True, False], [True, True, False]]) @@ -481,6 +705,11 @@ def _call_setitem(self, x): x[0, ...] = 0 x[x > 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, ...), 0) + x = paddle.static.setitem(x, x > 0, self.value) + return x + def _get_answer(self): self.data[0, ...] = 0 self.data[self.data > 0] = self.value @@ -803,9 +1032,14 @@ def set_dtype(self): self.dtype = "int32" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -827,9 +1061,14 @@ def set_dtype(self): self.dtype = "int64" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -851,9 +1090,14 @@ def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -875,9 +1119,14 @@ def set_dtype(self): self.dtype = "float64" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -899,9 +1148,14 @@ def set_dtype(self): self.dtype = "bool" def _call_setitem(self, x): - value = paddle.full(shape=[1], fill_value=False, dtype=self.dtype) + value = paddle.full(shape=[], fill_value=False, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[], fill_value=False, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = False @@ -925,6 +1179,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -936,6 +1194,10 @@ def set_value(self): def _call_setitem(self, x): x[0:1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 1), self.value) + return x + def _get_answer(self): self.data[0:1] = self.value @@ -949,6 +1211,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -964,6 +1230,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = paddle.assign(self.value) # x is Paddle.Tensor + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, paddle.assign(self.value)) + return x + def _get_answer(self): self.data[0] = self.value @@ -978,6 +1248,12 @@ def set_shape(self): def _call_setitem(self, x): x[:, 0] = paddle.assign(self.value) # x is Paddle.Tensor + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(None), 0), paddle.assign(self.value) + ) + return x + def _get_answer(self): self.data[:, 0] = self.value @@ -997,6 +1273,10 @@ def _call_setitem(self, x): def _get_answer(self): self.data[:, 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(None), 0), self.value) + return x + def test_api(self): places = ['cpu'] if paddle.is_compiled_with_cuda(): @@ -1030,7 +1310,10 @@ def _value_type_error(self): ): x = paddle.ones(shape=self.shape, dtype=self.dtype) value = [1] - x[0] = value + if paddle.in_dynamic_mode(): + x[0] = value + else: + x = paddle.static.setitem(x, 0, value) def _dtype_error(self): with self.assertRaisesRegex( @@ -1043,7 +1326,10 @@ def _dtype_error(self): def _step_error(self): with self.assertRaisesRegex(ValueError, "step can not be 0"): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[0:1:0] = self.value + if paddle.in_dynamic_mode(): + x[0:1:0] = self.value + else: + x = paddle.static.setitem(x, slice(0, 1, 0), self.value) def _ellipsis_error(self): with self.assertRaisesRegex( @@ -1059,24 +1345,33 @@ def _ellipsis_error(self): def _bool_list_error(self): with self.assertRaises(TypeError): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[[True, False, 0]] = 0 + if paddle.in_dynamic_mode(): + x[[True, False, 0]] = 0 + else: + x = paddle.static.setitem(x, [True, False, 0], 0) with self.assertRaises(IndexError): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[[True, False], [True, False]] = 0 + if paddle.in_dynamic_mode(): + x[[True, False], [True, False]] = 0 + else: + x = paddle.static.setitem(x, ([True, False], [True, False]), 0) def _bool_tensor_error(self): with self.assertRaises(IndexError): x = paddle.ones(shape=self.shape, dtype=self.dtype) idx = paddle.assign([True, False, True]) - x[idx] = 0 + if paddle.in_dynamic_mode(): + x[idx] = 0 + else: + x = paddle.static.setitem(x, idx, 0) def _broadcast_mismatch(self): program = paddle.static.Program() with paddle.static.program_guard(program): x = paddle.ones(shape=self.shape, dtype=self.dtype) value = np.array([3, 4, 5, 6, 7]) - x[0] = value + x = paddle.static.setitem(x, 0, value) exe = paddle.static.Executor(paddle.CPUPlace()) with self.assertRaises(ValueError): exe.run(program) @@ -1104,7 +1399,10 @@ def forward(self, x, y): y = self.conv(y) var = y.flatten() - x[0, :, 0, 0] = var + if paddle.in_dynamic_mode(): + x[0, :, 0, 0] = var + else: + x = paddle.static.setitem(x, (0, slice(None), 0, 0), var) loss = paddle.mean(x) return loss, var, x @@ -1131,7 +1429,7 @@ def test_static(self): z = paddle.add(x, y) var = y[0, :] - z[0, :] = var + z = paddle.static.setitem(z, (0, slice(None)), var) prediction = paddle.static.nn.fc(x=z, size=2, activation='softmax') diff --git a/test/legacy_test/test_variable.py b/test/legacy_test/test_variable.py index dcbfedc0f6a23..f7338ce07e425 100644 --- a/test/legacy_test/test_variable.py +++ b/test/legacy_test/test_variable.py @@ -844,8 +844,7 @@ def run_setitem_list_index(self, array, index, value_np): name='value', shape=value_np.shape, dtype='float32' ) - x[index] = value - y = x + y = paddle.static.setitem(x, index, value) place = paddle.fluid.CPUPlace() prog = paddle.static.default_main_program() @@ -1042,9 +1041,8 @@ def test_static_graph_tensor_index_setitem_muti_dim(self): name='index_2', shape=index2.shape, dtype='int32' ) - x1[index_1, index_2] = value - x2[index_1] = value - + x1_out = paddle.static.setitem(x1, (index_1, index_2), value) + x2_out = paddle.static.setitem(x2, index_1, value) place = ( paddle.fluid.CPUPlace() if not paddle.fluid.core.is_compiled_with_cuda() @@ -1055,7 +1053,7 @@ def test_static_graph_tensor_index_setitem_muti_dim(self): exe = paddle.static.Executor(place) exe.run(paddle.static.default_startup_program()) - fetch_list = [x1.name, x2.name] + fetch_list = [x1_out.name, x2_out.name] setitem_pp = exe.run( prog, @@ -1124,10 +1122,10 @@ def test_static_graph_array_index_muti_dim(self): name='x2', shape=array.shape, dtype='float32' ) - x1[index_mod1, index_mod2] = 1 - x2[index_mod1] = 2.5 - y1 = x1[index_mod2, index_mod1] - y2 = x2[index_mod2] + x1_out = paddle.static.setitem(x1, (index_mod1, index_mod2), 1) + x2_out = paddle.static.setitem(x2, index_mod1, 2.5) + y1 = x1_out[index_mod2, index_mod1] + y2 = x2_out[index_mod2] place = ( paddle.fluid.CPUPlace() if not paddle.fluid.core.is_compiled_with_cuda() @@ -1137,7 +1135,7 @@ def test_static_graph_array_index_muti_dim(self): prog = paddle.static.default_main_program() exe = paddle.static.Executor(place) exe.run(paddle.static.default_startup_program()) - fetch_list = [x1.name, x2.name, y1.name, y2.name] + fetch_list = [x1_out.name, x2_out.name, y1.name, y2.name] setitem_pp = exe.run( prog, diff --git a/test/legacy_test/test_zero_dim_tensor.py b/test/legacy_test/test_zero_dim_tensor.py index 6080327a2da95..6f47f2d46b57a 100644 --- a/test/legacy_test/test_zero_dim_tensor.py +++ b/test/legacy_test/test_zero_dim_tensor.py @@ -3141,7 +3141,7 @@ def test_setitem(self): x = paddle.arange(2 * 3 * 4 * 5).reshape((2, 3, 4, 5)) x.stop_gradient = False out = x * 2 - out[1, 2, 3, 4] = 10 + out = paddle.static.setitem(out, (1, 2, 3, 4), 10) paddle.static.append_backward(out.sum()) prog = paddle.static.default_main_program() res = self.exe.run(prog, fetch_list=[out, x.grad_name]) @@ -3162,7 +3162,7 @@ def test_setitem(self): x.stop_gradient = False indice = paddle.full([], 1, dtype='int32') out = x * 1 - out[indice, indice] = 0.5 + out = paddle.static.setitem(out, (indice, indice), 0.5) paddle.static.append_backward(out.sum()) prog = paddle.static.default_main_program() res = self.exe.run(prog, fetch_list=[out, x.grad_name]) @@ -3181,7 +3181,7 @@ def test_setitem(self): v.stop_gradient = False indice = paddle.full([], 1, dtype='int32') out = x * 1 - out[indice] = v + out = paddle.static.setitem(out, indice, v) paddle.static.append_backward(out.sum()) prog = paddle.static.default_main_program() res = self.exe.run(prog, fetch_list=[out, x.grad_name, v.grad_name]) From c68513062caf5afedf4028480253964d647730f9 Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Tue, 11 Jul 2023 11:01:00 +0000 Subject: [PATCH 22/26] solve error in static-mode --- python/paddle/fluid/framework.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/python/paddle/fluid/framework.py b/python/paddle/fluid/framework.py index 43f8603d12395..849805b4965c5 100644 --- a/python/paddle/fluid/framework.py +++ b/python/paddle/fluid/framework.py @@ -2295,9 +2295,14 @@ def __getitem__(self, item): return _getitem_impl_(self, item) def __setitem__(self, item, value): - raise RuntimeError( - "In static mode, the __setitem__ (looks like: x[indices] = values) should not be used. Please use x = paddle.static.setitem(x, indices, values)" - ) + from .dygraph.base import in_declarative_mode + + if in_declarative_mode(): + return _setitem_impl_(self, item, value) + else: + raise RuntimeError( + "In static mode, the __setitem__ (looks like: x[indices] = values) should not be used. Please use x = paddle.static.setitem(x, indices, values)" + ) def get_value(self, scope=None): """ From 65d2c72a17ea7e24f4815c7c946cde523bd74630 Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Wed, 12 Jul 2023 03:54:37 +0000 Subject: [PATCH 23/26] fix ut --- test/legacy_test/test_set_value_op.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/legacy_test/test_set_value_op.py b/test/legacy_test/test_set_value_op.py index bc6e1903af3b0..d57ef686dfaf2 100644 --- a/test/legacy_test/test_set_value_op.py +++ b/test/legacy_test/test_set_value_op.py @@ -138,7 +138,7 @@ def _call_setitem(self, x): def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (slice(0, -1), slice(0, 2)), self.value) - return + return x def _get_answer(self): self.data[0:-1, 0:2] = self.value From 7b5c1c4ad35a3431bb99cbedeb1628c00fa6efa9 Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Thu, 13 Jul 2023 03:19:27 +0000 Subject: [PATCH 24/26] return a result for set_array_write --- python/paddle/fluid/variable_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/fluid/variable_index.py b/python/paddle/fluid/variable_index.py index 06522d981daa3..f9a7ecc274bea 100644 --- a/python/paddle/fluid/variable_index.py +++ b/python/paddle/fluid/variable_index.py @@ -634,7 +634,7 @@ def _setitem_for_tensor_array(var, item, value): item = paddle.cast(to_static_variable(item), dtype='int64') value = to_static_variable(value) - array_write(x=value, i=item, array=var) + return array_write(x=value, i=item, array=var) else: raise NotImplementedError( "Only support __setitem__ by Int/Variable in tensor_array, but gets {}".format( From a846b79ea2aefdc1038034815073c7ec419cf64c Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Thu, 13 Jul 2023 04:19:40 +0000 Subject: [PATCH 25/26] fix test_set_value_op_xpu --- python/paddle/static/nn/__init__.py | 1 - test/xpu/test_set_value_op_xpu.py | 334 +++++++++++++++++++++++++++- 2 files changed, 325 insertions(+), 10 deletions(-) diff --git a/python/paddle/static/nn/__init__.py b/python/paddle/static/nn/__init__.py index 993be065f2b06..879645612ba4f 100755 --- a/python/paddle/static/nn/__init__.py +++ b/python/paddle/static/nn/__init__.py @@ -60,7 +60,6 @@ from .control_flow import cond - __all__ = [ # noqa 'fc', 'batch_norm', diff --git a/test/xpu/test_set_value_op_xpu.py b/test/xpu/test_set_value_op_xpu.py index 71ca556fb83a3..3bf665f76a32c 100644 --- a/test/xpu/test_set_value_op_xpu.py +++ b/test/xpu/test_set_value_op_xpu.py @@ -61,6 +61,10 @@ def set_dtype(self): def _call_setitem(self, x): x[0, 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, 0), self.value) + return x + def _get_answer(self): self.data[0, 0] = self.value @@ -69,7 +73,7 @@ def _run_static(self): paddle.enable_static() with paddle.static.program_guard(self.program): x = paddle.ones(shape=self.shape, dtype=self.dtype) - self._call_setitem(x) + x = self._call_setitem_static_api(x) exe = paddle.static.Executor(self.place) out = exe.run(self.program, fetch_list=[x]) @@ -107,6 +111,10 @@ class XPUTestSetValueItemInt(XPUTestSetValueApi): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -117,6 +125,10 @@ def set_shape(self): def _call_setitem(self, x): x[0, 3, 4] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, 3, 4), self.value) + return x + def _get_answer(self): self.data[0, 3, 4] = self.value @@ -127,6 +139,10 @@ def set_shape(self): def _call_setitem(self, x): x[1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (1), self.value) + return x + def _get_answer(self): self.data[1] = self.value @@ -136,6 +152,10 @@ class XPUTestSetValueItemSlice(XPUTestSetValueApi): def _call_setitem(self, x): x[0:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 2), self.value) + return x + def _get_answer(self): self.data[0:2] = self.value @@ -143,6 +163,10 @@ class XPUTestSetValueItemSlice2(XPUTestSetValueApi): def _call_setitem(self, x): x[0:-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, -1), self.value) + return x + def _get_answer(self): self.data[0:-1] = self.value @@ -150,6 +174,12 @@ class XPUTestSetValueItemSlice3(XPUTestSetValueApi): def _call_setitem(self, x): x[0:-1, 0:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, -1), slice(0, 2)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2] = self.value @@ -157,6 +187,14 @@ class XPUTestSetValueItemSlice4(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, 1:2, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (slice(0, None), slice(1, 2), slice(None, None, None)), + self.value, + ) + return x + def _get_answer(self): self.data[0:, 1:2, :] = self.value @@ -164,6 +202,12 @@ class XPUTestSetValueItemSlice5(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, 1:1, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0), slice(1, 1), slice(None, None, None)), self.value + ) + return x + def _get_answer(self): self.data[0:, 1:1, :] = self.value @@ -186,6 +230,19 @@ def body(i, x): i = paddle.zeros(shape=(1,), dtype='int32') i, x = paddle.static.nn.while_loop(cond, body, [i, x]) + def _call_setitem_static_api(self, x): + def cond(i, x): + return i < 1 + + def body(i, x): + x = paddle.static.setitem(x, i, self.value) + i = i + 1 + return i, x + + i = paddle.zeros(shape=(1,), dtype='int32') + i, x = paddle.static.nn.while_loop(cond, body, [i, x]) + return x + def _get_answer(self): self.data[0] = self.value @@ -197,6 +254,10 @@ def set_shape(self): def _call_setitem(self, x): x[0:2:2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 2, 2), self.value) + return x + def _get_answer(self): self.data[0:2:2] = self.value @@ -207,6 +268,10 @@ def set_shape(self): def _call_setitem(self, x): x[0:-1:3] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, -1, 3), self.value) + return x + def _get_answer(self): self.data[0:-1:3] = self.value @@ -214,6 +279,12 @@ class XPUTestSetValueItemSliceStep3(XPUTestSetValueApi): def _call_setitem(self, x): x[0:-1, 0:2, ::2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, -1), slice(0, 2), slice(None, None, 2)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2, ::2] = self.value @@ -221,6 +292,14 @@ class XPUTestSetValueItemSliceStep4(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, 1:2:2, :] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (slice(0, None), slice(1, 2, 2), slice(None, None, None)), + self.value, + ) + return x + def _get_answer(self): self.data[0:, 1:2:2, :] = self.value @@ -241,6 +320,10 @@ def set_value(self): def _call_setitem(self, x): x[5:2:-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(5, 2, -1), self.value) + return x + def _get_answer(self): self.data[5:2:-1] = self.value @@ -261,6 +344,10 @@ def set_value(self): def _call_setitem(self, x): x[1::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(1, None, -1), self.value) + return x + def _get_answer(self): self.data[1::-1] = self.value @@ -280,6 +367,10 @@ def set_value(self): def _call_setitem(self, x): x[::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(None, None, -1), self.value) + return x + def _get_answer(self): self.data[::-1] = self.value @@ -290,6 +381,14 @@ def set_shape(self): def _call_setitem(self, x): x[2:0:-1, 0:2, ::-1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (slice(2, 0, -1), slice(0, 2), slice(None, None, -1)), + self.value, + ) + return x + def _get_answer(self): self.data[2:0:-1, 0:2, ::-1] = self.value @@ -302,11 +401,15 @@ def set_shape(self): def _call_setitem(self, x): x[2:-1:-2] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(2, -1, -2), self.value) + return x + def _get_answer(self): paddle.enable_static() with paddle.static.program_guard(self.program): x = paddle.ones(shape=self.shape, dtype=self.dtype) - self._call_setitem(x) + x = self._call_setitem_static_api(x) exe = paddle.static.Executor(paddle.CPUPlace()) self.data = exe.run(self.program, fetch_list=[x]) @@ -334,6 +437,12 @@ class XPUTestSetValueItemEllipsis1(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, ..., 1:] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(0, None), ..., slice(1, None)), self.value + ) + return x + def _get_answer(self): self.data[0:, ..., 1:] = self.value @@ -341,6 +450,10 @@ class XPUTestSetValueItemEllipsis2(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, ...] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (slice(0, None), ...), self.value) + return x + def _get_answer(self): self.data[0:, ...] = self.value @@ -348,6 +461,10 @@ class XPUTestSetValueItemEllipsis3(XPUTestSetValueApi): def _call_setitem(self, x): x[..., 1:] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (..., slice(1, None)), self.value) + return x + def _get_answer(self): self.data[..., 1:] = self.value @@ -355,6 +472,10 @@ class XPUTestSetValueItemEllipsis4(XPUTestSetValueApi): def _call_setitem(self, x): x[...] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (...), self.value) + return x + def _get_answer(self): self.data[...] = self.value @@ -370,6 +491,11 @@ def _call_setitem(self, x): zero = paddle.full([1], 0, dtype="int32") x[zero] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([1], 0, dtype="int32") + x = paddle.static.setitem(x, zero, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -385,6 +511,12 @@ def _call_setitem(self, x): two = paddle.full([1], 2, dtype="int64") x[zero:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([1], 0, dtype="int32") + two = paddle.full([1], 2, dtype="int64") + x = paddle.static.setitem(x, slice(zero, two), self.value) + return x + def _get_answer(self): self.data[0:2] = self.value @@ -400,6 +532,14 @@ def _call_setitem(self, x): two = paddle.full([1], 2, dtype="int64") x[zero:-1, 0:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([1], 0, dtype="int32") + two = paddle.full([1], 2, dtype="int64") + x = paddle.static.setitem( + x, (slice(zero, -1), slice(0, two)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2] = self.value @@ -415,6 +555,14 @@ def _call_setitem(self, x): two = paddle.full([1], 2, dtype="int64") x[0:-1, zero:2, 0:6:two] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([1], 0, dtype="int32") + two = paddle.full([1], 2, dtype="int64") + x = paddle.static.setitem( + x, (slice(0, -1), slice(zero, 2), slice(0, 6, two)), self.value + ) + return x + def _get_answer(self): self.data[0:-1, 0:2, ::2] = self.value @@ -430,6 +578,16 @@ def _call_setitem(self, x): two = paddle.full([1], 2, dtype="int64") x[zero:, 1:2:two, :] = self.value + def _call_setitem_static_api(self, x): + zero = paddle.full([1], 0, dtype="int32") + two = paddle.full([1], 2, dtype="int64") + x = paddle.static.setitem( + x, + (slice(zero, None), slice(1, 2, two), slice(None, None, None)), + self.value, + ) + return x + def _get_answer(self): self.data[0:, 1:2:2, :] = self.value @@ -448,6 +606,16 @@ def _call_setitem(self, x): zero = paddle.full([1], 0, dtype="int32") x[2:zero:minus1, 0:2, 10:-6:minus1] = self.value + def _call_setitem_static_api(self, x): + minus1 = paddle.full([1], -1, dtype="int32") + zero = paddle.full([1], 0, dtype="int32") + x = paddle.static.setitem( + x, + (slice(2, zero, minus1), slice(0, 2), slice(10, -6, minus1)), + self.value, + ) + return x + def _get_answer(self): self.data[2:0:-1, 0:2, ::-1] = self.value @@ -462,6 +630,10 @@ def set_dtype(self): def _call_setitem(self, x): x[None] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, None, self.value) + return x + def _get_answer(self): self.data[None] = self.value @@ -475,6 +647,10 @@ def set_dtype(self): def _call_setitem(self, x): x[0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, None, 1] = self.value @@ -488,6 +664,12 @@ def set_dtype(self): def _call_setitem(self, x): x[:, None, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(None, None, None), None, None, 1), self.value + ) + return x + def _get_answer(self): self.data[:, None, None, 1] = self.value @@ -501,6 +683,10 @@ def set_dtype(self): def _call_setitem(self, x): x[0, 0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, 0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, 0, None, 1] = self.value @@ -514,6 +700,10 @@ def set_dtype(self): def _call_setitem(self, x): x[0, None, 0, None, 1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, None, 0, None, 1), self.value) + return x + def _get_answer(self): self.data[0, None, 0, None, 1] = self.value @@ -527,6 +717,10 @@ def set_dtype(self): def _call_setitem(self, x): x[None, 0, 0, None, 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (None, 0, 0, None, 0), self.value) + return x + def _get_answer(self): self.data[None, 0, 0, None, 0] = self.value @@ -540,6 +734,14 @@ def set_dtype(self): def _call_setitem(self, x): x[:, None, 1] = np.zeros(self.shape)[:, None, 0] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (slice(None, None, None), None, 1), + np.zeros(self.shape)[:, None, 0], + ) + return x + def _get_answer(self): self.data[:, None, 1] = np.zeros(self.shape)[:, None, 0] @@ -553,6 +755,14 @@ def set_dtype(self): def _call_setitem(self, x): x[:, 1, None] = np.zeros(self.shape)[:, 0, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (slice(None, None, None), 1, None), + np.zeros(self.shape)[:, 0, None], + ) + return x + def _get_answer(self): self.data[:, 1, None] = np.zeros(self.shape)[:, 0, None] @@ -566,6 +776,14 @@ def set_dtype(self): def _call_setitem(self, x): x[None, :, 1, ..., None] = np.zeros(self.shape)[0, 0, :, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (None, slice(None, None, None), 1, ..., None), + np.zeros(self.shape)[0, 0, :, None], + ) + return x + def _get_answer(self): self.data[None, :, 1, ..., None] = np.zeros(self.shape)[ 0, 0, :, None @@ -581,6 +799,14 @@ def set_dtype(self): def _call_setitem(self, x): x[..., None, :, None] = np.zeros(self.shape)[..., None, :, None] + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, + (..., None, slice(None, None, None), None), + np.zeros(self.shape)[..., None, :, None], + ) + return x + def _get_answer(self): self.data[..., None, :, None] = np.zeros(self.shape)[ ..., None, :, None @@ -597,6 +823,10 @@ def set_dtype(self): def _call_setitem(self, x): x[[True, False]] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [True, False], self.value) + return x + def _get_answer(self): self.data[[True, False]] = self.value @@ -610,6 +840,10 @@ def set_dtype(self): def _call_setitem(self, x): x[[False, False]] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [False, False], self.value) + return x + def _get_answer(self): self.data[[False, False]] = self.value @@ -623,6 +857,10 @@ def set_dtype(self): def _call_setitem(self, x): x[[False, True]] = np.zeros(self.shape[2]) + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, [False, True], np.zeros(self.shape[2])) + return x + def _get_answer(self): self.data[[False, True]] = np.zeros(self.shape[2]) @@ -637,6 +875,11 @@ def _call_setitem(self, x): idx = paddle.assign(np.array([False, True])) x[idx] = np.zeros(self.shape[2]) + def _call_setitem_static_api(self, x): + idx = paddle.assign(np.array([False, True])) + x = paddle.static.setitem(x, idx, np.zeros(self.shape[2])) + return x + def _get_answer(self): self.data[np.array([False, True])] = np.zeros(self.shape[2]) @@ -653,6 +896,13 @@ def _call_setitem(self, x): ) x[idx] = self.value + def _call_setitem_static_api(self, x): + idx = paddle.assign( + np.array([[False, True, False], [True, True, False]]) + ) + x = paddle.static.setitem(x, idx, self.value) + return x + def _get_answer(self): self.data[ np.array([[False, True, False], [True, True, False]]) @@ -669,6 +919,11 @@ def _call_setitem(self, x): x[0, ...] = 0 x[x > 0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, (0, ...), 0) + x = paddle.static.setitem(x, x > 0, self.value) + return x + def _get_answer(self): self.data[0, ...] = 0 self.data[self.data > 0] = self.value @@ -684,6 +939,11 @@ def _call_setitem(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -706,6 +966,11 @@ def _call_setitem(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -728,6 +993,11 @@ def _call_setitem(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = 3 @@ -752,6 +1022,13 @@ def _call_setitem(self, x): ) x[0, 1] = value + def _call_setitem_static_api(self, x): + value = paddle.full( + shape=[1], fill_value=False, dtype=self.dtype + ) + x = paddle.static.setitem(x, (0, 1), value) + return x + def _get_answer(self): self.data[0, 1] = False @@ -779,6 +1056,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -795,6 +1076,10 @@ def set_value(self): def _call_setitem(self, x): x[0:1] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, slice(0, 1), self.value) + return x + def _get_answer(self): self.data[0:1] = self.value @@ -813,6 +1098,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = self.value + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, self.value) + return x + def _get_answer(self): self.data[0] = self.value @@ -833,6 +1122,10 @@ def set_value(self): def _call_setitem(self, x): x[0] = paddle.assign(self.value) # x is Paddle.Tensor + def _call_setitem_static_api(self, x): + x = paddle.static.setitem(x, 0, paddle.assign(self.value)) + return x + def _get_answer(self): self.data[0] = self.value @@ -852,6 +1145,12 @@ def set_shape(self): def _call_setitem(self, x): x[:, 0] = paddle.assign(self.value) # x is Paddle.Tensor + def _call_setitem_static_api(self, x): + x = paddle.static.setitem( + x, (slice(None, None, None), 0), paddle.assign(self.value) + ) + return x + def _get_answer(self): self.data[:, 0] = self.value @@ -864,7 +1163,10 @@ def _value_type_error(self): ): x = paddle.ones(shape=self.shape, dtype=self.dtype) value = [1] - x[0] = value + if paddle.in_dynamic_mode(): + x[0] = value + else: + x = paddle.static.setitem(x, 0, value) def _dtype_error(self): with self.assertRaisesRegex( @@ -877,7 +1179,10 @@ def _dtype_error(self): def _step_error(self): with self.assertRaisesRegex(ValueError, "step can not be 0"): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[0:1:0] = self.value + if paddle.in_dynamic_mode(): + x[0:1:0] = self.value + else: + x = paddle.static.setitem(x, slice(0, 1, 0), self.value) def _ellipsis_error(self): with self.assertRaisesRegex( @@ -893,24 +1198,35 @@ def _ellipsis_error(self): def _bool_list_error(self): with self.assertRaises(TypeError): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[[True, False, 0]] = 0 + if paddle.in_dynamic_mode(): + x[[True, False, 0]] = 0 + else: + x = paddle.static.setitem(x, [True, False, 0], 0) with self.assertRaises(IndexError): x = paddle.ones(shape=self.shape, dtype=self.dtype) - x[[True, False], [True, False]] = 0 + if paddle.in_dynamic_mode(): + x[[True, False], [True, False]] = 0 + else: + x = paddle.static.setitem( + x, ([True, False], [True, False]), 0 + ) def _bool_tensor_error(self): with self.assertRaises(IndexError): x = paddle.ones(shape=self.shape, dtype=self.dtype) idx = paddle.assign([True, False, True]) - x[idx] = 0 + if paddle.in_dynamic_mode(): + x[idx] = 0 + else: + x = paddle.static.setitem(x, idx, 0) def _broadcast_mismatch(self): program = paddle.static.Program() with paddle.static.program_guard(program): x = paddle.ones(shape=self.shape, dtype=self.dtype) value = np.array([3, 4, 5, 6, 7]) - x[0] = value + x = paddle.static.setitem(x, 0, value) exe = paddle.static.Executor(paddle.XPUPlace(0)) with self.assertRaises(ValueError): exe.run(program) @@ -952,7 +1268,7 @@ def test_static(self): z = paddle.add(x, y) var = y[0, :] - z[0, :] = var + z = paddle.static.setitem(z, (0, slice(None)), var) prediction = paddle.static.nn.fc( x=z, size=2, activation='softmax' From 60686fd5dbdeed9db218980cfda7f41dd457711a Mon Sep 17 00:00:00 2001 From: zoooo0820 Date: Mon, 17 Jul 2023 03:39:31 +0000 Subject: [PATCH 26/26] code is different in dynamic / static mode --- python/paddle/distribution/multinomial.py | 9 ++-- .../incubate/optimizer/functional/lbfgs.py | 20 +++++--- python/paddle/tensor/math.py | 33 +++++++----- .../vision/transforms/functional_tensor.py | 50 ++++++++++++------- 4 files changed, 73 insertions(+), 39 deletions(-) diff --git a/python/paddle/distribution/multinomial.py b/python/paddle/distribution/multinomial.py index 8b01a2fb85bf4..f8e8ab3a0ba68 100644 --- a/python/paddle/distribution/multinomial.py +++ b/python/paddle/distribution/multinomial.py @@ -130,9 +130,12 @@ def log_prob(self, value): logits, value = paddle.broadcast_tensors( [paddle.log(self.probs), value] ) - logits = paddle.static.setitem( - logits, (value == 0) & (paddle.isinf(logits)), 0 - ) + if paddle.in_dynamic_mode(): + logits[(value == 0) & (paddle.isinf(logits))] = 0 + else: + logits = paddle.static.setitem( + logits, (value == 0) & (paddle.isinf(logits)), 0 + ) return ( paddle.lgamma(value.sum(-1) + 1) diff --git a/python/paddle/incubate/optimizer/functional/lbfgs.py b/python/paddle/incubate/optimizer/functional/lbfgs.py index ad3e07a745d63..06d8ba748c018 100644 --- a/python/paddle/incubate/optimizer/functional/lbfgs.py +++ b/python/paddle/incubate/optimizer/functional/lbfgs.py @@ -182,9 +182,12 @@ def cond(i, q, ai_vec): return i != tail def body(i, q, ai_vec): - ai_vec = paddle.static.setitem( - ai_vec, i, rhok_vec[i] * paddle.dot(sk_vec[i], q) - ) + if paddle.in_dynamic_mode(): + ai_vec[i] = rhok_vec[i] * paddle.dot(sk_vec[i], q) + else: + ai_vec = paddle.static.setitem( + ai_vec, i, rhok_vec[i] * paddle.dot(sk_vec[i], q) + ) q = q - ai_vec[i] * yk_vec[i] i = (i - 1).mod(history_size) return i, q, ai_vec @@ -238,9 +241,14 @@ def body(i, r): lambda: paddle.full(shape=[1], fill_value=1000.0, dtype=dtype), lambda: 1.0 / rhok_inv, ) - sk_vec = paddle.static.setitem(sk_vec, head, sk) - yk_vec = paddle.static.setitem(yk_vec, head, yk) - rhok_vec = paddle.static.setitem(rhok_vec, head, rhok) + if paddle.in_dynamic_mode(): + sk_vec[head] = sk + yk_vec[head] = yk + rhok_vec[head] = rhok + else: + sk_vec = paddle.static.setitem(sk_vec, head, sk) + yk_vec = paddle.static.setitem(yk_vec, head, yk) + rhok_vec = paddle.static.setitem(rhok_vec, head, rhok) head = (head + 1) % history_size def true_fn(tail): diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index eaa7d1a4a6bd5..c2b37647acfc1 100644 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -5716,19 +5716,26 @@ def vander(x, n=None, increasing=False, name=None): res = paddle.empty([x.shape[0], n], dtype=x.dtype) - if n > 0: - res = paddle.static.setitem( - res, (slice(None), 0), paddle.to_tensor([1], dtype=x.dtype) - ) - if n > 1: - res = paddle.static.setitem( - res, (slice(None), slice(1, None)), x[:, None] - ) - res = paddle.static.setitem( - res, - (slice(None), slice(1, None)), - paddle.cumprod(res[:, 1:], dim=-1), - ) + if paddle.in_dynamic_mode(): + if n > 0: + res[:, 0] = paddle.to_tensor([1], dtype=x.dtype) + if n > 1: + res[:, 1:] = x[:, None] + res[:, 1:] = paddle.cumprod(res[:, 1:], dim=-1) + else: + if n > 0: + res = paddle.static.setitem( + res, (slice(None), 0), paddle.to_tensor([1], dtype=x.dtype) + ) + if n > 1: + res = paddle.static.setitem( + res, (slice(None), slice(1, None)), x[:, None] + ) + res = paddle.static.setitem( + res, + (slice(None), slice(1, None)), + paddle.cumprod(res[:, 1:], dim=-1), + ) res = res[:, ::-1] if not increasing else res return res diff --git a/python/paddle/vision/transforms/functional_tensor.py b/python/paddle/vision/transforms/functional_tensor.py index c4d0c2d04ce99..e7b57a011baeb 100644 --- a/python/paddle/vision/transforms/functional_tensor.py +++ b/python/paddle/vision/transforms/functional_tensor.py @@ -398,6 +398,17 @@ def rotate( 0.0, ] matrix = paddle.to_tensor(matrix, place=img.place) + + matrix[2] += ( + matrix[0] * (-rotn_center[0] - post_trans[0]) + + matrix[1] * (-rotn_center[1] - post_trans[1]) + + rotn_center[0] + ) + matrix[5] += ( + matrix[3] * (-rotn_center[0] - post_trans[0]) + + matrix[4] * (-rotn_center[1] - post_trans[1]) + + rotn_center[1] + ) else: angle = angle / 180 * math.pi matrix = paddle.concat( @@ -410,22 +421,22 @@ def rotate( paddle.zeros([1]), ] ) - matrix = paddle.static.setitem( - matrix, - 2, - matrix[2] - + matrix[0] * (-rotn_center[0] - post_trans[0]) - + matrix[1] * (-rotn_center[1] - post_trans[1]) - + rotn_center[0], - ) - matrix = paddle.static.setitem( - matrix, - 5, - matrix[5] - + matrix[3] * (-rotn_center[0] - post_trans[0]) - + matrix[4] * (-rotn_center[1] - post_trans[1]) - + rotn_center[1], - ) + matrix = paddle.static.setitem( + matrix, + 2, + matrix[2] + + matrix[0] * (-rotn_center[0] - post_trans[0]) + + matrix[1] * (-rotn_center[1] - post_trans[1]) + + rotn_center[0], + ) + matrix = paddle.static.setitem( + matrix, + 5, + matrix[5] + + matrix[3] * (-rotn_center[0] - post_trans[0]) + + matrix[4] * (-rotn_center[1] - post_trans[1]) + + rotn_center[1], + ) matrix = matrix.reshape((1, 2, 3)) @@ -628,7 +639,12 @@ def erase(img, i, j, h, w, v, inplace=False): if not inplace: img = img.clone() - img = paddle.static.setitem(img, (..., slice(i, i + h), slice(j, j + w)), v) + if paddle.in_dynamic_mode(): + img[..., i : i + h, j : j + w] = v + else: + img = paddle.static.setitem( + img, (..., slice(i, i + h), slice(j, j + w)), v + ) return img