Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

disable __setitem__ in static mode & add API paddle.static.setitem with dy2st strategy #53682

Merged
merged 33 commits into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3dfa3cc
add paddle.static.setitem
zoooo0820 Apr 20, 2023
c7730e5
add some help doc
zoooo0820 Apr 20, 2023
5df24af
support setitem
Aurelius84 Apr 23, 2023
9ada910
support machanism
Aurelius84 Apr 23, 2023
44944b2
add more unittest
Aurelius84 Apr 24, 2023
aa0247f
remove usless code
Aurelius84 Apr 24, 2023
dc99e44
merge develop
zoooo0820 May 10, 2023
788f8ac
raise error in static setitem
zoooo0820 May 10, 2023
5f9f919
add static api
zoooo0820 May 11, 2023
c4853e0
fix d2s UT
zoooo0820 May 11, 2023
4218a96
remove static only for both-used code
zoooo0820 May 16, 2023
69da71a
fix bool set_value in static, fix set_value_op UT
zoooo0820 May 16, 2023
825f058
fix unittests
zoooo0820 May 18, 2023
3d60e1a
[May case some error]: remove inplace-version check
zoooo0820 May 18, 2023
9b6d777
add two test case for dy2st
zoooo0820 May 18, 2023
bb0c13e
fix function in vision
zoooo0820 May 19, 2023
f7e1641
fix dy2st setitem support, refine UT case
zoooo0820 May 26, 2023
84a1bff
merge dev
zoooo0820 May 26, 2023
51345e1
fix slice in static_mode
NotHaozi Jul 10, 2023
d8ad56b
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
NotHaozi Jul 10, 2023
dfd777f
add ParametersMap
NotHaozi Jul 10, 2023
8d8eb6a
remove pop
NotHaozi Jul 10, 2023
e8ecda1
modify place
NotHaozi Jul 11, 2023
df0debc
[fix]: variable is also a tensor
NotHaozi Jul 11, 2023
0d706e0
merge develop & solve conflict
zoooo0820 Jul 11, 2023
3013d67
rewrite some ut & remove slicetransformer in dy2st
zoooo0820 Jul 11, 2023
0caea01
merge new strategy of setitem dy2st
zoooo0820 Jul 11, 2023
c685130
solve error in static-mode
zoooo0820 Jul 11, 2023
65d2c72
fix ut
zoooo0820 Jul 12, 2023
2da88ee
Merge branch 'develop' into fix_d2s
zoooo0820 Jul 12, 2023
7b5c1c4
return a result for set_array_write
zoooo0820 Jul 13, 2023
a846b79
fix test_set_value_op_xpu
zoooo0820 Jul 13, 2023
60686fd
code is different in dynamic / static mode
zoooo0820 Jul 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion python/paddle/distribution/multinomial.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,12 @@ def log_prob(self, value):
logits, value = paddle.broadcast_tensors(
[paddle.log(self.probs), value]
)
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)
Expand Down
9 changes: 8 additions & 1 deletion python/paddle/fluid/framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -2295,7 +2295,14 @@ def __getitem__(self, item):
return _getitem_impl_(self, item)

def __setitem__(self, item, value):
return _setitem_impl_(self, item, value)
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):
"""
Expand Down
38 changes: 31 additions & 7 deletions python/paddle/fluid/variable_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,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

Expand Down Expand Up @@ -617,7 +619,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

from .framework import Variable

assert (
Expand All @@ -632,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(
Expand Down Expand Up @@ -807,17 +809,31 @@ 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
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
)

return output


# the item is a tensor of bool
Expand Down Expand Up @@ -848,11 +864,19 @@ 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)
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
29 changes: 20 additions & 9 deletions python/paddle/incubate/optimizer/functional/lbfgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,23 @@ 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):
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
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)

Expand Down Expand Up @@ -234,10 +241,14 @@ 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
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):
Expand Down
15 changes: 14 additions & 1 deletion python/paddle/jit/dy2static/convert_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
_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

Expand Down Expand Up @@ -48,6 +48,19 @@ def convert_load(x):
TODO:(@xiongkun) may run convert_load in dygraph mode, which should be fixed.
"""
return _convert_into_variable(x)

# get the new output of the var
if in_declarative_mode() and 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


Expand Down
31 changes: 31 additions & 0 deletions python/paddle/jit/dy2static/program_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,36 @@ 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 _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',
Expand Down Expand Up @@ -1386,6 +1416,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):
Expand Down
1 change: 1 addition & 0 deletions python/paddle/static/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 additions & 0 deletions python/paddle/static/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__ = []


Expand Down Expand Up @@ -342,3 +344,28 @@ def __eq__(self, other):

def __ne__(self, other):
return not self == other


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)
25 changes: 20 additions & 5 deletions python/paddle/tensor/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -5716,11 +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[:, 0] = paddle.to_tensor([1], dtype=x.dtype)
if n > 1:
res[:, 1:] = x[:, None]
res[:, 1:] = 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

Expand Down
Loading