“d83b861a511937c8bb7527c59435ef2d0965a649”上不存在“develop/doc_cn/design/tensor_array.html”
未验证 提交 d4571470 编写于 作者: W wanghuancoder 提交者: GitHub

Del old dygraph varbase (#52236)

* delete old dygraph op test
上级 b8850521
...@@ -56,11 +56,7 @@ from .framework.dtype import bool # noqa: F401 ...@@ -56,11 +56,7 @@ from .framework.dtype import bool # noqa: F401
from .framework.dtype import complex64 # noqa: F401 from .framework.dtype import complex64 # noqa: F401
from .framework.dtype import complex128 # noqa: F401 from .framework.dtype import complex128 # noqa: F401
if fluid.framework.global_var._in_eager_mode_: Tensor = framework.core.eager.Tensor # noqa: F401
Tensor = framework.core.eager.Tensor
else:
from .framework import VarBase as Tensor # noqa: F401
Tensor.__qualname__ = 'Tensor' # noqa: F401 Tensor.__qualname__ = 'Tensor' # noqa: F401
import paddle.distributed # noqa: F401 import paddle.distributed # noqa: F401
import paddle.sysconfig # noqa: F401 import paddle.sysconfig # noqa: F401
......
...@@ -179,7 +179,7 @@ class AmpScaler: ...@@ -179,7 +179,7 @@ class AmpScaler:
scaled.backward() scaled.backward()
scaler.minimize(optimizer, scaled) scaler.minimize(optimizer, scaled)
""" """
check_type(var, "var", core.VarBase, 'AmpScaler.scale()') check_type(var, "var", core.eager.Tensor, 'AmpScaler.scale()')
if not self._enable: if not self._enable:
return var return var
......
...@@ -266,7 +266,7 @@ class Engine: ...@@ -266,7 +266,7 @@ class Engine:
specs.append(spec) specs.append(spec)
else: else:
specs.append(spec.batch(batch_size)) specs.append(spec.batch(batch_size))
elif isinstance(item, (Variable, core.VarBase, core.eager.Tensor)): elif isinstance(item, (Variable, core.eager.Tensor)):
spec = InputSpec.from_tensor(item, name) spec = InputSpec.from_tensor(item, name)
_adjust_item_spec(num_shards, spec) _adjust_item_spec(num_shards, spec)
if batch_size is None: if batch_size is None:
......
...@@ -31,7 +31,7 @@ __all__ = [] ...@@ -31,7 +31,7 @@ __all__ = []
def detach_variable(inputs): def detach_variable(inputs):
out = [] out = []
for inp in inputs: for inp in inputs:
if not isinstance(inp, (core.eager.Tensor, core.VarBase)): if not isinstance(inp, core.eager.Tensor):
out.append(inp) out.append(inp)
continue continue
...@@ -172,7 +172,7 @@ class RecomputeFunction(PyLayer): ...@@ -172,7 +172,7 @@ class RecomputeFunction(PyLayer):
detached_inputs = detach_variable(tuple(inputs)) detached_inputs = detach_variable(tuple(inputs))
outputs = ctx.run_function(*detached_inputs, **ctx.kwargs) outputs = ctx.run_function(*detached_inputs, **ctx.kwargs)
if isinstance(outputs, (core.VarBase, core.eager.Tensor)): if isinstance(outputs, core.eager.Tensor):
outputs = (outputs,) outputs = (outputs,)
assert len(outputs) == len(args) assert len(outputs) == len(args)
...@@ -185,7 +185,7 @@ class RecomputeFunction(PyLayer): ...@@ -185,7 +185,7 @@ class RecomputeFunction(PyLayer):
backward_inputs_with_grad = [] backward_inputs_with_grad = []
for i in range(len(outputs)): for i in range(len(outputs)):
if ( if (
isinstance(outputs[i], (core.VarBase, core.eager.Tensor)) isinstance(outputs[i], core.eager.Tensor)
and not outputs[i].stop_gradient and not outputs[i].stop_gradient
): ):
forward_outputs_with_grad.append(outputs[i]) forward_outputs_with_grad.append(outputs[i])
...@@ -206,13 +206,13 @@ class RecomputeFunction(PyLayer): ...@@ -206,13 +206,13 @@ class RecomputeFunction(PyLayer):
grads = tuple( grads = tuple(
inp._grad_ivar() inp._grad_ivar()
for inp in detached_inputs for inp in detached_inputs
if isinstance(inp, (core.VarBase, core.eager.Tensor)) if isinstance(inp, core.eager.Tensor)
) )
else: else:
grads = [ grads = [
inp._grad_ivar() inp._grad_ivar()
for inp in detached_inputs for inp in detached_inputs
if isinstance(inp, (core.VarBase, core.eager.Tensor)) if isinstance(inp, core.eager.Tensor)
] ]
return grads return grads
......
...@@ -220,7 +220,7 @@ class _HPRecomputeFunction(PyLayer): ...@@ -220,7 +220,7 @@ class _HPRecomputeFunction(PyLayer):
detached_inputs = detach_variable(tuple(inputs)) detached_inputs = detach_variable(tuple(inputs))
outputs = ctx.run_function(*detached_inputs, **ctx.kwargs) outputs = ctx.run_function(*detached_inputs, **ctx.kwargs)
if isinstance(outputs, (core.VarBase, core.eager.Tensor)): if isinstance(outputs, core.eager.Tensor):
outputs = (outputs,) outputs = (outputs,)
assert len(outputs) == len(args) assert len(outputs) == len(args)
...@@ -229,7 +229,7 @@ class _HPRecomputeFunction(PyLayer): ...@@ -229,7 +229,7 @@ class _HPRecomputeFunction(PyLayer):
for i in range(len(outputs)): for i in range(len(outputs)):
if ( if (
isinstance(outputs[i], (core.VarBase, core.eager.Tensor)) isinstance(outputs[i], core.eager.Tensor)
and not outputs[i].stop_gradient and not outputs[i].stop_gradient
): ):
forward_outputs_with_grad.append(outputs[i]) forward_outputs_with_grad.append(outputs[i])
...@@ -245,7 +245,7 @@ class _HPRecomputeFunction(PyLayer): ...@@ -245,7 +245,7 @@ class _HPRecomputeFunction(PyLayer):
grads = tuple( grads = tuple(
inp._grad_ivar() inp._grad_ivar()
for inp in detached_inputs for inp in detached_inputs
if isinstance(inp, (core.VarBase, core.eager.Tensor)) if isinstance(inp, core.eager.Tensor)
) )
return grads return grads
......
...@@ -156,7 +156,7 @@ def broadcast_input_data(hcg, *inputs, **kwargs): ...@@ -156,7 +156,7 @@ def broadcast_input_data(hcg, *inputs, **kwargs):
place = eval(f"paddle.{dev.upper()}Place")(dev_idx) place = eval(f"paddle.{dev.upper()}Place")(dev_idx)
for v in inputs: for v in inputs:
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
with framework.no_grad(): with framework.no_grad():
if in_dygraph_mode() and not eval(f"v.place.is_{dev}_place")(): if in_dygraph_mode() and not eval(f"v.place.is_{dev}_place")():
v_gpu = v._copy_to(place, True) v_gpu = v._copy_to(place, True)
...@@ -167,7 +167,7 @@ def broadcast_input_data(hcg, *inputs, **kwargs): ...@@ -167,7 +167,7 @@ def broadcast_input_data(hcg, *inputs, **kwargs):
logger.warning("it doesn't support data type {}".format(type(v))) logger.warning("it doesn't support data type {}".format(type(v)))
for k, v in kwargs.items(): for k, v in kwargs.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
with framework.no_grad(): with framework.no_grad():
if in_dygraph_mode() and not eval(f"v.place.is_{dev}_place")(): if in_dygraph_mode() and not eval(f"v.place.is_{dev}_place")():
v_gpu = v._copy_to(place, True) v_gpu = v._copy_to(place, True)
......
...@@ -44,7 +44,7 @@ from paddle.distributed.fleet.base.private_helper_function import ( # noqa: F40 ...@@ -44,7 +44,7 @@ from paddle.distributed.fleet.base.private_helper_function import ( # noqa: F40
from paddle.distributed.fleet.launch_utils import check_backend from paddle.distributed.fleet.launch_utils import check_backend
# (TODO: GhostScreaming) It will be removed later. # (TODO: GhostScreaming) It will be removed later.
from paddle.framework import ParamBase, _set_expected_place from paddle.framework import _set_expected_place
from paddle.framework import base as imperative_base from paddle.framework import base as imperative_base
from paddle.framework import core, in_dygraph_mode, to_variable from paddle.framework import core, in_dygraph_mode, to_variable
from paddle.nn.layer import layers from paddle.nn.layer import layers
...@@ -158,14 +158,14 @@ def sync_params_buffers( ...@@ -158,14 +158,14 @@ def sync_params_buffers(
): ):
model_vars = [] model_vars = []
for _, param in model._obtain_parameters_buffers().items(): for _, param in model._obtain_parameters_buffers().items():
if not isinstance(param, (core.VarBase, core.eager.Tensor)): if not isinstance(param, core.eager.Tensor):
raise TypeError( raise TypeError(
"The data type of '%s' must be Varbase or eager.Tensor" "The data type of '%s' must be Varbase or eager.Tensor"
% param.name % param.name
) )
# is_distributed param not need to sync when in mp mode # is_distributed param not need to sync when in mp mode
if isinstance(param, (ParamBase, core.eager.Tensor)): if isinstance(param, core.eager.Tensor):
if is_model_parallel: if is_model_parallel:
if hasattr(param, "is_distributed") and param.is_distributed: if hasattr(param, "is_distributed") and param.is_distributed:
continue continue
...@@ -379,9 +379,7 @@ class DataParallel(layers.Layer): ...@@ -379,9 +379,7 @@ class DataParallel(layers.Layer):
self.find_unused_parameters = find_unused_parameters self.find_unused_parameters = find_unused_parameters
self.grad_need_sync = True self.grad_need_sync = True
self.group = group self.group = group
self.var_dtype = ( self.var_dtype = core.eager.Tensor
core.eager.Tensor if in_dygraph_mode() else core.VarBase
)
# NOTE(chenweihang): The ParallelStrategy here is not strictly a strategy. # NOTE(chenweihang): The ParallelStrategy here is not strictly a strategy.
# It just stores some environment variables, which can be constructed by # It just stores some environment variables, which can be constructed by
...@@ -491,7 +489,7 @@ class DataParallel(layers.Layer): ...@@ -491,7 +489,7 @@ class DataParallel(layers.Layer):
) )
def _find_varbase(self, obj): def _find_varbase(self, obj):
var_type = core.eager.Tensor if in_dygraph_mode() else core.VarBase var_type = core.eager.Tensor
if isinstance(obj, var_type): if isinstance(obj, var_type):
return [obj] return [obj]
if isinstance(obj, (list, tuple)): if isinstance(obj, (list, tuple)):
......
...@@ -116,32 +116,22 @@ def check_type(input, input_name, expected_type, op_name, extra_message=''): ...@@ -116,32 +116,22 @@ def check_type(input, input_name, expected_type, op_name, extra_message=''):
return return
# NOTE: `in_declarative_mode` is used to determined whether this op is called under # NOTE: `in_declarative_mode` is used to determined whether this op is called under
# @to_static in transformation from dygrah to static layer. We add VarBase in # @to_static in transformation from dygrah to static layer. We add Tensor in
# expected_type to skip checking because varBase may be created and used in unusual way. # expected_type to skip checking because Tensor may be created and used in unusual way.
from .dygraph.base import in_declarative_mode from .dygraph.base import in_declarative_mode
# Need a better design to be fix this. # Need a better design to be fix this.
if in_declarative_mode(): if in_declarative_mode():
if not isinstance(expected_type, tuple): if not isinstance(expected_type, tuple):
expected_type = (expected_type,) expected_type = (expected_type,)
expected_type += (core.VarBase,) expected_type += (core.eager.Tensor,)
if _in_eager_without_dygraph_check(): elif isinstance(input, core.eager.Tensor):
expected_type += (core.eager.Tensor,)
elif isinstance(input, core.VarBase):
raise TypeError( raise TypeError(
"Please use `with fluid.dygraph.guard()` as context or `fluid.enable_dygraph()` to switch to imperative mode firstly. " "Please use `with fluid.dygraph.guard()` as context or `fluid.enable_dygraph()` to switch to imperative mode firstly. "
"Because received '{}' in {} is a imperative Variable.".format( "Because received '{}' in {} is a imperative Variable.".format(
input_name, op_name input_name, op_name
) )
) )
elif hasattr(core, "eager"):
if isinstance(input, core.eager.Tensor):
raise TypeError(
"Please use `with fluid.dygraph.guard()` as context or `fluid.enable_dygraph()` to switch to imperative mode firstly. "
"Because received '{}' in {} is a imperative Variable.".format(
input_name, op_name
)
)
if not isinstance(input, expected_type): if not isinstance(input, expected_type):
raise TypeError( raise TypeError(
"The type of '%s' in %s must be %s, but received %s. %s" "The type of '%s' in %s must be %s, but received %s. %s"
......
...@@ -127,20 +127,18 @@ def _convert_into_variable(tensor): ...@@ -127,20 +127,18 @@ def _convert_into_variable(tensor):
""" """
Convert Varbase into Variable. Convert Varbase into Variable.
""" """
if isinstance(tensor, (core.eager.Tensor, core.VarBase)): if isinstance(tensor, core.eager.Tensor):
# Check whether has been created before. # Check whether has been created before.
new_var = tensor.block._find_var_recursive(tensor.name) new_var = tensor.block._find_var_recursive(tensor.name)
if new_var is not None: if new_var is not None:
assert isinstance(new_var, framework.Variable) assert isinstance(new_var, framework.Variable)
# Convert ParamBase into Parameter with same attributes in dy2stat. # Convert EagerParamBase into Parameter with same attributes in dy2stat.
elif isinstance( elif isinstance(tensor, framework.EagerParamBase):
tensor, (framework.EagerParamBase, framework.ParamBase)
):
new_var = tensor._to_static_var(to_parameter=True) new_var = tensor._to_static_var(to_parameter=True)
else: else:
# Note(Aurelius84): Convert VarBase in self._buffers into Variable with # Note(Aurelius84): Convert Tensor in self._buffers into Variable with
# same attributes and set persistable=True to allow saving this var. # same attributes and set persistable=True to allow saving this var.
# Because users can create a VarBase in `__init__` like a # Because users can create a Tensor in `__init__` like a
# `mask` Tensor or `hidden_0` in RNN layers, which is equivalent to a Parameter # `mask` Tensor or `hidden_0` in RNN layers, which is equivalent to a Parameter
# and necessary for inferring. It will be pruned if it's not necessary for inferring. # and necessary for inferring. It will be pruned if it's not necessary for inferring.
...@@ -587,7 +585,6 @@ def guard(place=None): ...@@ -587,7 +585,6 @@ def guard(place=None):
train = framework.Program() train = framework.Program()
startup = framework.Program() startup = framework.Program()
tracer = Tracer() tracer = Tracer()
VarBase = core.VarBase
if place is not None: if place is not None:
expected_place = _get_paddle_place(place) expected_place = _get_paddle_place(place)
...@@ -757,24 +754,14 @@ def grad( ...@@ -757,24 +754,14 @@ def grad(
if isinstance(in_out_list, (list, tuple)): if isinstance(in_out_list, (list, tuple)):
assert len(in_out_list) > 0, "{} cannot be empty".format(name) assert len(in_out_list) > 0, "{} cannot be empty".format(name)
for each_var in in_out_list: for each_var in in_out_list:
if _in_eager_without_dygraph_check(): assert isinstance(
assert isinstance( each_var, core.eager.Tensor
each_var, core.eager.Tensor ), "Elements of {} must be Tensor".format(name)
), "Elements of {} must be Tensor".format(name)
else:
assert isinstance(
each_var, core.VarBase
), "Elements of {} must be Variable".format(name)
return in_out_list return in_out_list
else: else:
if _in_eager_without_dygraph_check(): assert isinstance(
assert isinstance( in_out_list, core.eager.Tensor
in_out_list, core.eager.Tensor ), "{} must be Tensor or list of Tensor".format(name)
), "{} must be Tensor or list of Tensor".format(name)
else:
assert isinstance(
in_out_list, core.VarBase
), "{} must be Variable or list of Variable".format(name)
return [in_out_list] return [in_out_list]
outputs = check_in_out(outputs, 'outputs') outputs = check_in_out(outputs, 'outputs')
...@@ -786,14 +773,9 @@ def grad( ...@@ -786,14 +773,9 @@ def grad(
for each_var in grad_outputs: for each_var in grad_outputs:
if each_var is not None: if each_var is not None:
if _in_eager_without_dygraph_check(): assert isinstance(
assert isinstance( each_var, core.eager.Tensor
each_var, core.eager.Tensor ), "grad_outputs must be None, a Variable or a list containing None or Variables"
), "grad_outputs must be None, a Variable or a list containing None or Variables"
else:
assert isinstance(
each_var, core.VarBase
), "grad_outputs must be None, a Variable or a list containing None or Variables"
else: else:
grad_outputs = [] grad_outputs = []
...@@ -804,21 +786,16 @@ def grad( ...@@ -804,21 +786,16 @@ def grad(
if no_grad_vars is None: if no_grad_vars is None:
no_grad_vars = [] no_grad_vars = []
elif isinstance(no_grad_vars, (core.VarBase, core.eager.Tensor)): elif isinstance(no_grad_vars, core.eager.Tensor):
no_grad_vars = [no_grad_vars] no_grad_vars = [no_grad_vars]
elif isinstance(no_grad_vars, core.eager.Tensor): elif isinstance(no_grad_vars, core.eager.Tensor):
no_grad_vars = [no_grad_vars] no_grad_vars = [no_grad_vars]
elif isinstance(no_grad_vars, (list, tuple, set)): elif isinstance(no_grad_vars, (list, tuple, set)):
no_grad_vars = list(no_grad_vars) no_grad_vars = list(no_grad_vars)
for var in no_grad_vars: for var in no_grad_vars:
if _in_eager_without_dygraph_check(): assert isinstance(
assert isinstance( var, core.eager.Tensor
var, core.eager.Tensor ), "no_grad_vars can only contains Tensor"
), "no_grad_vars can only contains Tensor"
else:
assert isinstance(
var, core.VarBase
), "no_grad_vars can only contains Variable"
else: else:
if _in_eager_without_dygraph_check(): if _in_eager_without_dygraph_check():
raise AssertionError( raise AssertionError(
...@@ -932,7 +909,6 @@ def to_variable(value, name=None, zero_copy=None, dtype=None): ...@@ -932,7 +909,6 @@ def to_variable(value, name=None, zero_copy=None, dtype=None):
tuple, tuple,
np.ndarray, np.ndarray,
core.eager.Tensor, core.eager.Tensor,
core.VarBase,
framework.Variable, framework.Variable,
core.Tensor, core.Tensor,
core.LoDTensor, core.LoDTensor,
...@@ -942,10 +918,10 @@ def to_variable(value, name=None, zero_copy=None, dtype=None): ...@@ -942,10 +918,10 @@ def to_variable(value, name=None, zero_copy=None, dtype=None):
"The type of 'value' in fluid.dygraph.to_variable must be %s, but received %s." "The type of 'value' in fluid.dygraph.to_variable must be %s, but received %s."
% (support_type, type(value)) % (support_type, type(value))
) )
if isinstance(value, (core.eager.Tensor, core.VarBase, framework.Variable)): if isinstance(value, (core.eager.Tensor, framework.Variable)):
return value return value
elif isinstance(value, (core.Tensor, core.LoDTensor)): elif isinstance(value, (core.Tensor, core.LoDTensor)):
return core.VarBase(value) return core.eager.Tensor(value)
else: else:
if isinstance( if isinstance(
framework._current_expected_place(), framework.core.CPUPlace framework._current_expected_place(), framework.core.CPUPlace
...@@ -974,21 +950,11 @@ def to_variable(value, name=None, zero_copy=None, dtype=None): ...@@ -974,21 +950,11 @@ def to_variable(value, name=None, zero_copy=None, dtype=None):
if value.dtype != dtype: if value.dtype != dtype:
value = value.astype(dtype) value = value.astype(dtype)
if _in_eager_without_dygraph_check(): return core.eager.Tensor(
return core.eager.Tensor( value,
value, framework._current_expected_place(),
framework._current_expected_place(), False,
False, zero_copy,
zero_copy, name if name else None,
name if name else None, True,
True, )
)
else:
py_var = core.VarBase(
value=value,
place=framework._current_expected_place(),
persistable=False,
zero_copy=zero_copy,
name=name if name else '',
)
return py_var
...@@ -62,7 +62,6 @@ _complex_dtypes = [ ...@@ -62,7 +62,6 @@ _complex_dtypes = [
core.VarDesc.VarType.COMPLEX128, core.VarDesc.VarType.COMPLEX128,
] ]
_already_patch_varbase = False
_already_patch_eager_tensor = False _already_patch_eager_tensor = False
...@@ -251,10 +250,7 @@ def monkey_patch_math_varbase(): ...@@ -251,10 +250,7 @@ def monkey_patch_math_varbase():
# 2. create varbase for scalar # 2. create varbase for scalar
lhs_dtype = self.dtype lhs_dtype = self.dtype
if framework.global_var._in_eager_mode_: other_var_should_be = core.eager.Tensor
other_var_should_be = core.eager.Tensor
else:
other_var_should_be = core.VarBase
if not isinstance(other_var, other_var_should_be): if not isinstance(other_var, other_var_should_be):
if isinstance(other_var, complex): if isinstance(other_var, complex):
import paddle import paddle
...@@ -483,17 +479,11 @@ def monkey_patch_math_varbase(): ...@@ -483,17 +479,11 @@ def monkey_patch_math_varbase():
'__ne__', '__ne__',
] ]
global _already_patch_varbase
global _already_patch_eager_tensor global _already_patch_eager_tensor
if framework.global_var._in_eager_mode_: local_already_patch = _already_patch_eager_tensor
local_already_patch = _already_patch_eager_tensor _already_patch_eager_tensor = True
_already_patch_eager_tensor = True local_tensor = core.eager.Tensor
local_tensor = core.eager.Tensor
else:
local_already_patch = _already_patch_varbase
_already_patch_varbase = True
local_tensor = core.VarBase
if not local_already_patch: if not local_already_patch:
if framework.global_var._in_eager_mode_: if framework.global_var._in_eager_mode_:
......
...@@ -26,7 +26,6 @@ from .. import unique_name ...@@ -26,7 +26,6 @@ from .. import unique_name
from ..framework import ( from ..framework import (
Variable, Variable,
Parameter, Parameter,
ParamBase,
_getitem_impl_, _getitem_impl_,
_setitem_impl_, _setitem_impl_,
EagerParamBase, EagerParamBase,
...@@ -94,12 +93,12 @@ def monkey_patch_varbase(): ...@@ -94,12 +93,12 @@ def monkey_patch_varbase():
**Notes**: **Notes**:
**This API is ONLY available in Dygraph mode** **This API is ONLY available in Dygraph mode**
Transform a VarBase into static Variable with same attributes. It's a low level interface used Transform a Tensor into static Variable with same attributes. It's a low level interface used
in dy2static and shall not be called directly. in dy2static and shall not be called directly.
Args: Args:
to_parameter (bool): It takes effect only if the input a VarBase. If set True, to_parameter (bool): It takes effect only if the input a Tensor. If set True,
the VarBase will be converted into framework.Parameters. Otherwise, it will the Tensor will be converted into framework.Parameters. Otherwise, it will
be converted into framework.Variable. Default False. be converted into framework.Variable. Default False.
Examples: Examples:
...@@ -120,7 +119,7 @@ def monkey_patch_varbase(): ...@@ -120,7 +119,7 @@ def monkey_patch_varbase():
# It will fail. So, for propery that different between dynamic and static graph, should not getattr(self, attr, None). # It will fail. So, for propery that different between dynamic and static graph, should not getattr(self, attr, None).
attr_not_need_keys = ['grad', 'T', 'place', '_place_str'] attr_not_need_keys = ['grad', 'T', 'place', '_place_str']
param_keys = ['stop_gradient', 'trainable'] param_keys = ['stop_gradient', 'trainable']
if isinstance(self, (ParamBase, EagerParamBase)): if isinstance(self, EagerParamBase):
attr_kwargs = self.__dict__.copy() attr_kwargs = self.__dict__.copy()
for key in param_keys: for key in param_keys:
attr_kwargs[key] = getattr(self, key) attr_kwargs[key] = getattr(self, key)
...@@ -144,7 +143,7 @@ def monkey_patch_varbase(): ...@@ -144,7 +143,7 @@ def monkey_patch_varbase():
attr_kwargs.update(kwargs) attr_kwargs.update(kwargs)
if to_parameter or isinstance(self, (ParamBase, EagerParamBase)): if to_parameter or isinstance(self, EagerParamBase):
del attr_kwargs['persistable'] del attr_kwargs['persistable']
# NOTE(Aurelius84): All parameters should be placed into global block. # NOTE(Aurelius84): All parameters should be placed into global block.
attr_kwargs['block'] = attr_kwargs['block'].program.global_block() attr_kwargs['block'] = attr_kwargs['block'].program.global_block()
...@@ -183,13 +182,10 @@ def monkey_patch_varbase(): ...@@ -183,13 +182,10 @@ def monkey_patch_varbase():
out = linear(t) # call with different weight out = linear(t) # call with different weight
""" """
if framework.global_var._in_eager_mode_: base_tensor = core.eager.Tensor
base_tensor = core.eager.Tensor
else:
base_tensor = core.VarBase
assert isinstance( assert isinstance(
value, (np.ndarray, base_tensor, dict, str) value, (np.ndarray, base_tensor, dict, str)
), "Variable set_value function, arguments type only support Variable, numpy, VarBase, dict, string." ), "Variable set_value function, arguments type only support Variable, numpy, Tensor, dict, string."
if isinstance(value, (dict, str)): if isinstance(value, (dict, str)):
assert len(self) == len( assert len(self) == len(
...@@ -219,8 +215,7 @@ def monkey_patch_varbase(): ...@@ -219,8 +215,7 @@ def monkey_patch_varbase():
self.name, self.dtype, dtype self.name, self.dtype, dtype
) )
# NOTE(wuweilong): self could be VarBase or Tensor, the subsequent behavior are defined in different files # NOTE(wuweilong): self could be Tensor, the subsequent behavior are defined in different files
# if self is VarBase, method value() return Variable that bindded in imperative.cc, get_tensor() bindded in pybind.cc
# if self is Tensor, method value() return self that defined in this file, get_tensor() defined in eager_method.cc # if self is Tensor, method value() return self that defined in this file, get_tensor() defined in eager_method.cc
# this Interface behavior will be unifed in the future. # this Interface behavior will be unifed in the future.
self.value().get_tensor().set( self.value().get_tensor().set(
...@@ -665,7 +660,7 @@ def monkey_patch_varbase(): ...@@ -665,7 +660,7 @@ def monkey_patch_varbase():
def __str__(self): def __str__(self):
""" """
Convert a VarBase object to a readable string. Convert a Tensor object to a readable string.
Returns(str): A readable string. Returns(str): A readable string.
...@@ -680,14 +675,9 @@ def monkey_patch_varbase(): ...@@ -680,14 +675,9 @@ def monkey_patch_varbase():
# [[0.30574632, 0.55739117, 0.30902600, 0.39413780, 0.44830436], # [[0.30574632, 0.55739117, 0.30902600, 0.39413780, 0.44830436],
# [0.79010487, 0.53972793, 0.09495186, 0.44267157, 0.72112119]]) # [0.79010487, 0.53972793, 0.09495186, 0.44267157, 0.72112119]])
""" """
if framework.global_var._in_eager_mode_: from paddle.tensor.to_string import tensor_to_string
from paddle.tensor.to_string import tensor_to_string
return tensor_to_string(self)
else:
from paddle.tensor.to_string import to_string
return to_string(self) return tensor_to_string(self)
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
""" """
...@@ -714,10 +704,7 @@ def monkey_patch_varbase(): ...@@ -714,10 +704,7 @@ def monkey_patch_varbase():
raise RuntimeError( raise RuntimeError(
"Only Leaf Tensor support the deepcopy at the moment, non-Leaf Tensors contains graph information that does't support deepcopy" "Only Leaf Tensor support the deepcopy at the moment, non-Leaf Tensors contains graph information that does't support deepcopy"
) )
if framework.global_var._in_eager_mode_: new_varbase = core.eager.Tensor()
new_varbase = core.eager.Tensor()
else:
new_varbase = core.VarBase()
new_varbase.name = self.name + unique_name.generate("_deepcopy") new_varbase.name = self.name + unique_name.generate("_deepcopy")
memo[id(self)] = new_varbase memo[id(self)] = new_varbase
new_varbase.copy_(self, True) new_varbase.copy_(self, True)
...@@ -1055,26 +1042,19 @@ def monkey_patch_varbase(): ...@@ -1055,26 +1042,19 @@ def monkey_patch_varbase():
("to_dense", to_dense), ("to_dense", to_dense),
("to_sparse_coo", to_sparse_coo), ("to_sparse_coo", to_sparse_coo),
): ):
if framework.global_var._in_eager_mode_: setattr(core.eager.Tensor, method_name, method)
setattr(core.eager.Tensor, method_name, method)
else: setattr(core.eager.Tensor, "_set_grad_ivar", _set_grad_ivar)
setattr(core.VarBase, method_name, method) setattr(core.eager.Tensor, "value", value)
setattr(core.eager.Tensor, "cpu", cpu)
if framework.global_var._in_eager_mode_: setattr(core.eager.Tensor, "cuda", cuda)
setattr(core.eager.Tensor, "_set_grad_ivar", _set_grad_ivar) setattr(core.eager.Tensor, "pin_memory", pin_memory)
setattr(core.eager.Tensor, "value", value) setattr(core.eager.Tensor, "_slice", _slice)
setattr(core.eager.Tensor, "cpu", cpu) setattr(core.eager.Tensor, "_numel", _numel)
setattr(core.eager.Tensor, "cuda", cuda) setattr(core.eager.Tensor, "_uva", _uva)
setattr(core.eager.Tensor, "pin_memory", pin_memory) setattr(core.eager.Tensor, "_clear_data", _clear_data)
setattr(core.eager.Tensor, "_slice", _slice) setattr(core.eager.Tensor, "__hash__", __hash__)
setattr(core.eager.Tensor, "_numel", _numel) setattr(core.eager.Tensor, "_use_gpudnn", _use_gpudnn)
setattr(core.eager.Tensor, "_uva", _uva)
setattr(core.eager.Tensor, "_clear_data", _clear_data)
setattr(core.eager.Tensor, "__hash__", __hash__)
setattr(core.eager.Tensor, "_use_gpudnn", _use_gpudnn)
else:
setattr(core.VarBase, "__name__", "Tensor")
setattr(core.VarBase, "grad", grad)
global _already_patch_repr global _already_patch_repr
if not _already_patch_repr: if not _already_patch_repr:
......
...@@ -192,9 +192,9 @@ extra_op_attrs = { ...@@ -192,9 +192,9 @@ extra_op_attrs = {
# to make sure in most case, we find new dygraph mode first with only one if statement. # to make sure in most case, we find new dygraph mode first with only one if statement.
def _update_monkey_methods(is_eager): def _update_monkey_methods():
""" """
Update monkey methods of VarBase or eager.Tensor while Update monkey methods of Tensor or eager.Tensor while
switching eager mode and legacy mode. switching eager mode and legacy mode.
""" """
from paddle import _C_ops, _legacy_C_ops from paddle import _C_ops, _legacy_C_ops
...@@ -204,46 +204,23 @@ def _update_monkey_methods(is_eager): ...@@ -204,46 +204,23 @@ def _update_monkey_methods(is_eager):
global _already_patch_eager_tensor global _already_patch_eager_tensor
global _already_patch_varbase global _already_patch_varbase
assert isinstance(is_eager, bool) if not _already_patch_eager_tensor:
# switch into eager mode monkey_patch_varbase()
if is_eager: monkey_patch_math_varbase()
if not _already_patch_eager_tensor:
monkey_patch_varbase()
monkey_patch_math_varbase()
_already_patch_eager_tensor = True _already_patch_eager_tensor = True
# switch back into legacy mode
else:
if not _already_patch_varbase:
monkey_patch_varbase()
monkey_patch_math_varbase()
_already_patch_varbase = True
# switch Paddle.Tensor bind type # switch Paddle.Tensor bind type
_switch_tensor_bind_type(is_eager) _switch_tensor_bind_type()
def _switch_tensor_bind_type(is_eager): def _switch_tensor_bind_type():
import paddle import paddle
if is_eager: paddle.Tensor = core.eager.Tensor
paddle.Tensor = core.eager.Tensor
else:
paddle.Tensor = core.VarBase
paddle.Tensor.__qualname__ = 'Tensor' paddle.Tensor.__qualname__ = 'Tensor'
def _enable_legacy_dygraph():
global_var._in_eager_mode_ = False
_update_monkey_methods(is_eager=False)
def _disable_legacy_dygraph():
global_var._in_eager_mode_ = True
_update_monkey_methods(is_eager=True)
def _in_eager_without_dygraph_check(): def _in_eager_without_dygraph_check():
return global_var._in_eager_mode_ return global_var._in_eager_mode_
...@@ -253,36 +230,6 @@ def _in_eager_without_dygraph_check(): ...@@ -253,36 +230,6 @@ def _in_eager_without_dygraph_check():
_is_first_import_ = True _is_first_import_ = True
def _fallback_legacy_dygraph():
global _is_first_import_
need_fallback = False
# Only enable eager on CPU/GPU/XPU
is_not_support = (
core.is_compiled_with_npu()
or core.is_compiled_with_ipu()
or core.is_compiled_with_mlu()
)
if global_var._in_eager_mode_ and is_not_support:
# switch into legacy dygraph mode
warnings.warn(
"We will fallback into legacy dygraph on NPU/XPU/MLU/IPU/ROCM devices. Because we only support new eager dygraph mode on CPU/GPU currently. "
)
global_var._in_eager_mode_ = False
if not _is_first_import_:
_enable_legacy_dygraph()
need_fallback = True
need_fallback = False
_is_first_import_ = False
return need_fallback
# switch into legacy mode if need while import paddle
_fallback_legacy_dygraph()
def in_dygraph_mode(): def in_dygraph_mode():
""" """
...@@ -319,19 +266,6 @@ def _non_static_mode(): ...@@ -319,19 +266,6 @@ def _non_static_mode():
return global_var._dygraph_tracer_ is not None return global_var._dygraph_tracer_ is not None
@signature_safe_contextmanager
def _test_eager_guard(place=None):
# FIXME(dev): We haven't fully verified eager mode on NPU et.al but
# only GPU/CPU/XPU. Remove this after we improve this feature.
already_fallback = _fallback_legacy_dygraph()
if not already_fallback:
_disable_legacy_dygraph()
try:
yield
finally:
pass
global_ipu_index = -1 global_ipu_index = -1
global_ipu_stage = -1 global_ipu_stage = -1
ipu_index_attr_name = 'ipu_index' ipu_index_attr_name = 'ipu_index'
...@@ -634,11 +568,11 @@ def _set_pipeline_stage(stage): ...@@ -634,11 +568,11 @@ def _set_pipeline_stage(stage):
# NOTE(zhiqiu): This decorator is used for the APIs of Variable which is only # NOTE(zhiqiu): This decorator is used for the APIs of Variable which is only
# used to make Variable and VarBase has same interfaces, like numpy. Since VarBase is not exposed in our # used to make Variable and Tensor has same interfaces, like numpy. Since Tensor is not exposed in our
# official docments, logically, we want to keep VarBase and logically consistent. While, actually, # official docments, logically, we want to keep Tensor and logically consistent. While, actually,
# in our implementation, there some APIs not supported, like numpy, because Variable contains the desc. # in our implementation, there some APIs not supported, like numpy, because Variable contains the desc.
# So, those APIs are listed under class Variable to generate docs only. # So, those APIs are listed under class Variable to generate docs only.
# TODO(zhiqiu): We should make VarBase consistent with Variable in future, for example, by inheritting # TODO(zhiqiu): We should make Tensor consistent with Variable in future, for example, by inheritting
# same base class. # same base class.
def _fake_interface_only_(func): def _fake_interface_only_(func):
def __impl__(*args, **kwargs): def __impl__(*args, **kwargs):
...@@ -759,23 +693,6 @@ def _set_expected_place(place): ...@@ -759,23 +693,6 @@ def _set_expected_place(place):
_set_dygraph_tracer_expected_place(place) _set_dygraph_tracer_expected_place(place)
# TODO(zhiqiu): remove this function.
def _var_base_to_np(var_base):
"""
convert VarBase tp numpy
Args:
var_base(VarBase) : the VarBase to convert
Returns (np.ndarray): the np.ndarray contain the value of VarBase
"""
warnings.warn(
"paddle.fluid.framework._var_base_to_np is deprecated, please use var_base.numpy() instead of _var_base_to_np(var_base)."
)
return var_base.numpy(False)
def _cpu_num(): def _cpu_num():
if "CPU_NUM" not in os.environ.keys(): if "CPU_NUM" not in os.environ.keys():
if multiprocessing.cpu_count() > 1: if multiprocessing.cpu_count() > 1:
...@@ -1392,24 +1309,15 @@ def _varbase_creator( ...@@ -1392,24 +1309,15 @@ def _varbase_creator(
if not isinstance(dtype, core.VarDesc.VarType): if not isinstance(dtype, core.VarDesc.VarType):
dtype = convert_np_dtype_to_dtype_(dtype) dtype = convert_np_dtype_to_dtype_(dtype)
if global_var._in_eager_mode_: eager_tensor = core.eager.Tensor(
eager_tensor = core.eager.Tensor( dtype if dtype else core.VarDesc.VarType.FP32,
dtype if dtype else core.VarDesc.VarType.FP32, list(shape) if shape else [],
list(shape) if shape else [], name,
name, type if type else core.VarDesc.VarType.LOD_TENSOR,
type if type else core.VarDesc.VarType.LOD_TENSOR, True if persistable else False,
True if persistable else False, )
) eager_tensor.retain_grads()
eager_tensor.retain_grads() return eager_tensor
return eager_tensor
else:
return core.VarBase(
dtype if dtype else core.VarDesc.VarType.FP32,
list(shape) if shape else [],
name,
type if type else core.VarDesc.VarType.LOD_TENSOR,
True if persistable else False,
)
def _all_is_type(vals, expected_type): def _all_is_type(vals, expected_type):
...@@ -3141,7 +3049,7 @@ class Operator: ...@@ -3141,7 +3049,7 @@ class Operator:
in_arg_names.append(arg) in_arg_names.append(arg)
elif isinstance(arg, bytes): elif isinstance(arg, bytes):
in_arg_names.append(arg.decode()) in_arg_names.append(arg.decode())
elif isinstance(arg, (Variable, core.VarBase)): elif isinstance(arg, (Variable, core.eager.Tensor)):
in_arg_names.append(arg.name) in_arg_names.append(arg.name)
else: else:
raise TypeError( raise TypeError(
...@@ -4274,7 +4182,7 @@ class Block: ...@@ -4274,7 +4182,7 @@ class Block:
op_desc = self.desc.append_op() op_desc = self.desc.append_op()
inputs = kwargs.get("inputs", None) inputs = kwargs.get("inputs", None)
outputs = kwargs.get("outputs", None) outputs = kwargs.get("outputs", None)
# NOTE(Aurelius84): In case of @to_static, all VarBase(s) should # NOTE(Aurelius84): In case of @to_static, all Tensor(s) should
# be converted into Variable(s) with same name and block location. # be converted into Variable(s) with same name and block location.
# This is ONE and ONLY logic of type transformation of dy2static. # This is ONE and ONLY logic of type transformation of dy2static.
ignore_ops = { ignore_ops = {
...@@ -7205,155 +7113,7 @@ class Parameter(Variable, metaclass=ParameterMetaClass): ...@@ -7205,155 +7113,7 @@ class Parameter(Variable, metaclass=ParameterMetaClass):
__repr__ = __str__ __repr__ = __str__
class ParamBase(core.VarBase): class EagerParamBase(core.eager.Tensor):
"""
ParamBase is derived from Tensor( Which is the concept in Dygraph Mode).
A ParamBase is a persistable Tensor, and will be updated by optimizers
after each iteration.
The training of a neural network is essentially the updating of
its ParamBase.
Relative to a general Tensor, a ParamBase has several its own
member variables:
Args:
trainable(bool): True if the ParamBase need to be updated after
iterations.
optimize_attr(map): ParamBase attributes related with optimizing.
Currently, it only contains 'learning_rate'.
Default: {'learning_rate': 1.0}
regularizer(WeightDecayRegularizer): The Regularizer which will
be applied on the ParamBase. Default: None
do_model_average(bool): True if the model average strategy will
be applied on this ParamBase.
need_clip (bool): Whether the parameter gradient need to be cliped
in optimizer. Default is True.
"""
@dygraph_only
def __init__(self, shape, dtype, **kwargs):
if shape is None:
raise ValueError("The shape of Parameter should not be None")
if dtype is None:
raise ValueError("The dtype of Parameter should not be None")
for each in shape:
if each < 0:
raise ValueError(
"Each dimension of shape for Parameter must be greater than 0, but received %s"
% list(shape)
)
if dtype is not None:
if not isinstance(dtype, core.VarDesc.VarType):
dtype = convert_np_dtype_to_dtype_(dtype)
name = kwargs.get('name', unique_name.generate('_param_base'))
super().__init__(
dtype if dtype else core.VarDesc.VarType.FP32,
list(shape) if shape else [],
name,
core.VarDesc.VarType.LOD_TENSOR,
True,
)
trainable = kwargs.get('trainable', True)
self.stop_gradient = not trainable
self.optimize_attr = kwargs.get('optimize_attr', {'learning_rate': 1.0})
self.regularizer = kwargs.get('regularizer', None)
self.do_model_average = kwargs.get('do_model_average', None)
self.need_clip = kwargs.get('need_clip', True)
self.is_distributed = kwargs.get('is_distributed', False)
# self.block = default_main_program().global_block()
@property
def trainable(self):
return not self.stop_gradient
@trainable.setter
def trainable(self, trainable):
if isinstance(trainable, bool):
self.stop_gradient = not trainable
else:
raise ValueError(
"The type of trainable MUST be bool, but the type is ",
type(trainable),
)
def __str__(self):
"""
Convert a ParamBase object to a readable string.
Returns(str): A readable string.
Examples:
.. code-block:: python
import paddle
linear = paddle.nn.Linear(3, 3)
print(linear.weight)
# Parameter containing:
# Tensor(shape=[3, 3], dtype=float32, place=CUDAPlace(0), stop_gradient=False,
# [[ 0.48948765, 0.05829060, -0.25524026],
# [-0.70368278, 0.52986908, -0.68742192],
# [-0.54217887, 0.48439729, 0.34082305]])
"""
return "Parameter containing:\n{tensor}".format(
tensor=super().__str__()
)
def __deepcopy__(self, memo):
"""
Deep copy parameter, it will always performs Tensor copy.
Examples:
.. code-block:: python
import paddle
import copy
linear = paddle.nn.Linear(1, 3)
linear_copy = copy.deepcopy(linear)
print(linear.weight)
# Parameter containing:
# Tensor(shape=[1, 3], dtype=float32, place=CPUPlace, stop_gradient=False,
# [[-0.30929261, -0.90929240, -1.07851017]])
print(linear_copy.weight)
# Parameter containing:
# Tensor(shape=[1, 3], dtype=float32, place=CPUPlace, stop_gradient=False,
# [[-0.30929261, -0.90929240, -1.07851017]])
"""
state = copy.deepcopy(self.__dict__, memo)
state["name"] = self.name + unique_name.generate("_deepcopy")
new_param = ParamBase(self.shape, self.dtype, **state)
memo[id(self)] = new_param
new_param.copy_(self, True)
return new_param
def _copy_to(self, device, blocking):
state = copy.deepcopy(self.__dict__)
new_param = ParamBase(self.shape, self.dtype, **state)
core.varbase_copy(self, new_param, device, blocking)
return new_param
__repr__ = __str__
if hasattr(core, "eager"):
_core_eager_eagertensor = core.eager.Tensor
else:
_core_eager_eagertensor = object
class EagerParamBase(_core_eager_eagertensor):
""" """
EagerParamBase is derived from Tensor( Which is the concept in Eager-Dygraph Mode). EagerParamBase is derived from Tensor( Which is the concept in Eager-Dygraph Mode).
A EagerParamBase is a persistable Tensor, and will be updated by optimizers A EagerParamBase is a persistable Tensor, and will be updated by optimizers
......
...@@ -88,25 +88,15 @@ class LayerHelperBase: ...@@ -88,25 +88,15 @@ class LayerHelperBase:
""" """
if isinstance(value, np.ndarray): if isinstance(value, np.ndarray):
if _in_eager_without_dygraph_check(): return core.eager.Tensor(
return core.eager.Tensor( value,
value, _current_expected_place(),
_current_expected_place(), False,
False, False,
False, name if name else None,
name if name else None, True,
True, )
) elif isinstance(value, (Variable, core.eager.Tensor)):
else:
py_var = core.VarBase(
value=value,
name=name if name else '',
persistable=False,
place=_current_expected_place(),
zero_copy=False,
)
return py_var
elif isinstance(value, (core.VarBase, Variable, core.eager.Tensor)):
return value return value
else: else:
raise TypeError( raise TypeError(
......
...@@ -1053,7 +1053,7 @@ def assign_skip_lod_tensor_array(input, output): ...@@ -1053,7 +1053,7 @@ def assign_skip_lod_tensor_array(input, output):
return True return True
return False return False
if not isinstance(input, (Variable, core.VarBase)): if not isinstance(input, (Variable, core.eager.Tensor)):
if isinstance(output, Variable) and isinstance( if isinstance(output, Variable) and isinstance(
input, support_ret_buildin_type input, support_ret_buildin_type
): ):
......
...@@ -309,7 +309,7 @@ class Optimizer: ...@@ -309,7 +309,7 @@ class Optimizer:
self._learning_rate.step_num = global_step[0] self._learning_rate.step_num = global_step[0]
else: else:
raise RuntimeError( raise RuntimeError(
"Type not supprt, value in state dict must be [VarBase, Variable, numpy], the type is ", "Type not supprt, value in state dict must be [Tensor, Variable, numpy], the type is ",
type(global_step), type(global_step),
) )
...@@ -320,7 +320,7 @@ class Optimizer: ...@@ -320,7 +320,7 @@ class Optimizer:
load_para = state_dict[param.name] load_para = state_dict[param.name]
if isinstance(load_para, Variable): if isinstance(load_para, Variable):
load_para_np = load_para.numpy() load_para_np = load_para.numpy()
elif isinstance(load_para, core.VarBase): elif isinstance(load_para, core.eager.Tensor):
load_para_np = load_para.numpy() load_para_np = load_para.numpy()
elif isinstance(load_para, np.ndarray): elif isinstance(load_para, np.ndarray):
load_para_np = load_para load_para_np = load_para
......
...@@ -62,7 +62,7 @@ class TestLen(unittest.TestCase): ...@@ -62,7 +62,7 @@ class TestLen(unittest.TestCase):
else: else:
out = self.func(self.x_data) out = self.func(self.x_data)
if isinstance(out, fluid.core.VarBase): if isinstance(out, fluid.core.eager.Tensor):
out = out.numpy() out = out.numpy()
return out return out
......
...@@ -320,7 +320,7 @@ class TestTransformWhileLoop(unittest.TestCase): ...@@ -320,7 +320,7 @@ class TestTransformWhileLoop(unittest.TestCase):
def _run(self, to_static): def _run(self, to_static):
with fluid.dygraph.guard(self.place): with fluid.dygraph.guard(self.place):
# Set the input of dyfunc to VarBase # Set the input of dyfunc to Tensor
tensor_x = fluid.dygraph.to_variable(self.x, zero_copy=False) tensor_x = fluid.dygraph.to_variable(self.x, zero_copy=False)
if to_static: if to_static:
ret = paddle.jit.to_static(self.dyfunc)(tensor_x) ret = paddle.jit.to_static(self.dyfunc)(tensor_x)
......
...@@ -116,9 +116,7 @@ class TestWithNestedOutput(unittest.TestCase): ...@@ -116,9 +116,7 @@ class TestWithNestedOutput(unittest.TestCase):
self.assertTrue(len(dygraph_res) == len(static_res)) self.assertTrue(len(dygraph_res) == len(static_res))
for dy_var, st_var in zip(dygraph_res, static_res): for dy_var, st_var in zip(dygraph_res, static_res):
if isinstance( if isinstance(dy_var, fluid.core.eager.Tensor):
dy_var, (fluid.core.VarBase, fluid.core.eager.Tensor)
):
np.testing.assert_allclose( np.testing.assert_allclose(
dy_var.numpy(), st_var.numpy(), rtol=1e-05 dy_var.numpy(), st_var.numpy(), rtol=1e-05
) )
......
...@@ -282,7 +282,7 @@ class TestReturnBase(unittest.TestCase): ...@@ -282,7 +282,7 @@ class TestReturnBase(unittest.TestCase):
res = self.dygraph_func(self.input) res = self.dygraph_func(self.input)
if isinstance(res, (tuple, list)): if isinstance(res, (tuple, list)):
return tuple(r.numpy() for r in res) return tuple(r.numpy() for r in res)
elif isinstance(res, (core.VarBase, core.eager.Tensor)): elif isinstance(res, core.eager.Tensor):
return res.numpy() return res.numpy()
return res return res
......
...@@ -161,13 +161,13 @@ class TestPartialProgramRaiseError(unittest.TestCase): ...@@ -161,13 +161,13 @@ class TestPartialProgramRaiseError(unittest.TestCase):
concrete_program.parameters = params[0] concrete_program.parameters = params[0]
# TypeError: Type of self._params should be list or tuple, # TypeError: Type of self._params should be list or tuple,
# but received <class 'paddle.fluid.framework.ParamBase'>. # but received <class 'paddle.fluid.framework.EagerParamBase'>.
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
partial_program_from(concrete_program) partial_program_from(concrete_program)
params[0] = "linear.w.0" params[0] = "linear.w.0"
concrete_program.parameters = params concrete_program.parameters = params
# TypeError: Type of self._params[0] should be framework.ParamBase, # TypeError: Type of self._params[0] should be framework.EagerParamBase,
# but received <type 'str'>. # but received <type 'str'>.
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
partial_program_from(concrete_program) partial_program_from(concrete_program)
......
...@@ -53,7 +53,7 @@ class TestTransformWhileLoop(unittest.TestCase): ...@@ -53,7 +53,7 @@ class TestTransformWhileLoop(unittest.TestCase):
def _run(self, to_static): def _run(self, to_static):
with fluid.dygraph.guard(self.place): with fluid.dygraph.guard(self.place):
# Set the input of dyfunc to VarBase # Set the input of dyfunc to Tensor
tensor_x = fluid.dygraph.to_variable(self.x, zero_copy=False) tensor_x = fluid.dygraph.to_variable(self.x, zero_copy=False)
if to_static: if to_static:
ret = paddle.jit.to_static(self.dyfunc)(tensor_x) ret = paddle.jit.to_static(self.dyfunc)(tensor_x)
......
...@@ -21,7 +21,7 @@ from paddle import enable_static ...@@ -21,7 +21,7 @@ from paddle import enable_static
from paddle.fluid import core from paddle.fluid import core
sys.path.append("..") sys.path.append("..")
from op_test import OpTest, OpTestTool, convert_float_to_uint16 from eager_op_test import OpTest, OpTestTool, convert_float_to_uint16
from test_pool2d_op import ( from test_pool2d_op import (
TestPool2D_Op_Mixin, TestPool2D_Op_Mixin,
adaptive_end_index, adaptive_end_index,
......
# Copyright (c) 2018 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 functools
import os
import random
import struct
import sys
import unittest
import warnings
from collections import defaultdict
from copy import copy
import numpy as np
import paddle
from paddle import fluid
from paddle.fluid import core, unique_name
from paddle.fluid.backward import append_backward
from paddle.fluid.executor import Executor
from paddle.fluid.framework import (
OpProtoHolder,
Program,
_current_expected_place,
_disable_legacy_dygraph,
_enable_legacy_dygraph,
_in_eager_without_dygraph_check,
_test_eager_guard,
canonicalize_attrs,
in_dygraph_mode,
)
from paddle.fluid.op import Operator
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
from prim_op_test import OpTestUtils, PrimForwardChecker, PrimGradChecker
from testsuite import append_input_output, append_loss_ops, create_op, set_input
from white_list import (
check_shape_white_list,
compile_vs_runtime_white_list,
no_check_set_white_list,
no_grad_set_white_list,
op_accuracy_white_list,
op_threshold_white_list,
)
# For switch new eager mode globally
g_is_in_eager = _in_eager_without_dygraph_check()
g_enable_legacy_dygraph = (
_enable_legacy_dygraph if g_is_in_eager else lambda: None
)
g_disable_legacy_dygraph = (
_disable_legacy_dygraph if g_is_in_eager else lambda: None
)
def check_out_dtype(api_fn, in_specs, expect_dtypes, target_index=0, **configs):
"""
Determines whether dtype of output tensor is as expected.
Args:
api_fn(callable): paddle api function
in_specs(list[tuple]): list of shape and dtype information for constructing input tensor of api_fn, such as [(shape, dtype), (shape, dtype)].
expected_dtype(list[str]): expected dtype of output tensor.
target_index(int): indicate which one from in_specs to infer the dtype of output.
config(dict): other arguments of paddle api function
Example:
check_out_dtype(fluid.layers.pad_constant_like, [([2,3,2,3], 'float64'), ([1, 3, 1,3], )], ['float32', 'float64', 'int64'], target_index=1, pad_value=0.)
"""
paddle.enable_static()
for i, expect_dtype in enumerate(expect_dtypes):
with paddle.static.program_guard(paddle.static.Program()):
input_t = []
for index, spec in enumerate(in_specs):
if len(spec) == 1:
shape = spec[0]
dtype = expect_dtype if target_index == index else 'float32'
elif len(spec) == 2:
shape, dtype = spec
else:
raise ValueError(
"Value of in_specs[{}] should contains two elements: [shape, dtype]".format(
index
)
)
input_t.append(
paddle.static.data(
name='data_%s' % index, shape=shape, dtype=dtype
)
)
out = api_fn(*input_t, **configs)
out_dtype = fluid.data_feeder.convert_dtype(out.dtype)
if out_dtype != expect_dtype:
raise ValueError(
"Expected out.dtype is {}, but got {} from {}.".format(
expect_dtype, out_dtype, api_fn.__name__
)
)
def _set_use_system_allocator(value=None):
USE_SYSTEM_ALLOCATOR_FLAG = "FLAGS_use_system_allocator"
old_value = core.globals()[USE_SYSTEM_ALLOCATOR_FLAG]
value = old_value if value is None else value
core.globals()[USE_SYSTEM_ALLOCATOR_FLAG] = value
return old_value
def randomize_probability(batch_size, class_num, dtype='float32'):
prob = np.random.uniform(0.1, 1.0, size=(batch_size, class_num)).astype(
dtype
)
prob_sum = prob.sum(axis=1)
for i in range(len(prob)):
prob[i] /= prob_sum[i]
return prob
def get_numeric_gradient(
place,
scope,
op,
inputs,
input_to_check,
output_names,
delta=0.005,
in_place=False,
):
# FIXME: change this method by compile time concepts
set_input(scope, op, inputs, place)
def product(dim):
return functools.reduce(lambda a, b: a * b, dim, 1)
tensor_to_check = scope.find_var(input_to_check).get_tensor()
tensor_size = product(tensor_to_check.shape())
tensor_to_check_dtype = tensor_to_check._dtype()
if tensor_to_check_dtype == core.VarDesc.VarType.FP32:
tensor_to_check_dtype = np.float32
elif tensor_to_check_dtype == core.VarDesc.VarType.FP64:
tensor_to_check_dtype = np.float64
elif tensor_to_check_dtype == core.VarDesc.VarType.FP16:
tensor_to_check_dtype = np.float16
# set delta as np.float16, will automatic convert to float32, float64
delta = np.array(delta).astype(np.float16)
elif tensor_to_check_dtype == core.VarDesc.VarType.BF16:
tensor_to_check_dtype = np.float32
elif tensor_to_check_dtype == core.VarDesc.VarType.COMPLEX64:
tensor_to_check_dtype = np.complex64
elif tensor_to_check_dtype == core.VarDesc.VarType.COMPLEX128:
tensor_to_check_dtype = np.complex128
else:
raise ValueError(
"Not supported data type "
+ str(tensor_to_check_dtype)
+ ", tensor name : "
+ str(input_to_check)
)
def get_output():
sum = []
op.run(scope, place)
for output_name in output_names:
output_numpy = np.array(scope.find_var(output_name).get_tensor())
# numpy.dtype does not have bfloat16, thus we use numpy.uint16 to
# store bfloat16 data, and need to be converted to float to check
# the floating precision.
if tensor_to_check._dtype() == core.VarDesc.VarType.BF16:
output_numpy = convert_uint16_to_float(output_numpy)
sum.append(output_numpy.astype(tensor_to_check_dtype).mean())
return tensor_to_check_dtype(np.array(sum).sum() / len(output_names))
gradient_flat = np.zeros(shape=(tensor_size,), dtype=tensor_to_check_dtype)
def __get_elem__(tensor, i):
if tensor_to_check_dtype == np.float16:
numpy_tensor = np.array(tensor).astype(np.float16)
numpy_tensor = numpy_tensor.flatten()
return numpy_tensor[i]
elif tensor_to_check._dtype() == core.VarDesc.VarType.BF16:
numpy_tensor = np.array(tensor).astype(np.uint16)
numpy_tensor = numpy_tensor.flatten()
return struct.unpack(
'<f',
struct.pack('<I', np.uint32(numpy_tensor[i]) << np.uint32(16)),
)[0]
elif tensor_to_check_dtype == np.float32:
return tensor._get_float_element(i)
elif tensor_to_check_dtype == np.float64:
return tensor._get_double_element(i)
else:
raise TypeError(
"Unsupported test data type %s." % tensor_to_check_dtype
)
def __set_elem__(tensor, i, e):
if tensor_to_check_dtype == np.float16:
numpy_tensor = np.array(tensor).astype(np.float16)
shape = numpy_tensor.shape
numpy_tensor = numpy_tensor.flatten()
numpy_tensor[i] = e
numpy_tensor = numpy_tensor.reshape(shape)
tensor.set(numpy_tensor, place)
elif tensor_to_check._dtype() == core.VarDesc.VarType.BF16:
numpy_tensor = np.array(tensor).astype(np.uint16)
shape = numpy_tensor.shape
numpy_tensor = numpy_tensor.flatten()
numpy_tensor[i] = np.uint16(copy_bits_from_float_to_uint16(e))
numpy_tensor = numpy_tensor.reshape(shape)
tensor.set(numpy_tensor, place)
elif tensor_to_check_dtype == np.float32:
tensor._set_float_element(i, e)
elif tensor_to_check_dtype == np.float64:
tensor._set_double_element(i, e)
else:
raise TypeError(
"Unsupported test data type %s." % tensor_to_check_dtype
)
# we only compute gradient of one element each time.
# we use a for loop to compute the gradient of every element.
for i in range(tensor_size):
if in_place:
set_input(scope, op, inputs, place)
# get one input element throw it's index i.
origin = __get_elem__(tensor_to_check, i)
# add delta to it, run op and then get the sum of the result tensor.
x_pos = origin + delta
__set_elem__(tensor_to_check, i, x_pos)
y_pos = get_output()
if in_place:
set_input(scope, op, inputs, place)
x_neg = origin - delta
__set_elem__(tensor_to_check, i, x_neg)
y_neg = get_output()
__set_elem__(tensor_to_check, i, origin)
gradient_flat[i] = (y_pos - y_neg) / delta / 2
return gradient_flat.reshape(tensor_to_check.shape())
def skip_check_grad_ci(reason=None):
"""Decorator to skip check_grad CI.
Check_grad is required for Op test cases. However, there are some special
cases that do not need to do check_grad. This decorator is used to skip the
check_grad of the above cases.
Note: the execution of unit test will not be skipped. It just avoids check_grad
checking in tearDownClass method by setting a `no_need_check_grad` flag.
Example:
@skip_check_grad_ci(reason="For inference, check_grad is not required.")
class TestInference(OpTest):
"""
if not isinstance(reason, str):
raise AssertionError("The reason for skipping check_grad is required.")
def wrapper(cls):
cls.no_need_check_grad = True
return cls
return wrapper
def skip_check_inplace_ci(reason=None):
if not isinstance(reason, str):
raise AssertionError(
"The reason for skipping check_inplace is required."
)
def wrapper(cls):
cls.no_need_check_inplace = True
return cls
return wrapper
def copy_bits_from_float_to_uint16(f):
return struct.unpack('<I', struct.pack('<f', f))[0] >> 16
def convert_float_to_uint16(float_list, data_format="NCHW"):
if data_format == "NHWC":
float_list = np.transpose(float_list, [0, 3, 1, 2])
new_output = []
for x in np.nditer(float_list):
new_output.append(np.uint16(copy_bits_from_float_to_uint16(x)))
new_output = np.reshape(new_output, float_list.shape).view(np.uint16)
if data_format == "NHWC":
new_output = np.transpose(new_output, [0, 2, 3, 1])
return new_output
def convert_uint16_to_float(in_list):
in_list = np.asarray(in_list)
out = np.vectorize(
lambda x: struct.unpack(
'<f', struct.pack('<I', np.uint32(x) << np.uint32(16))
)[0],
otypes=[np.float32],
)(in_list.flat)
return np.reshape(out, in_list.shape)
class OpTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
'''Fix random seeds to remove randomness from tests'''
cls._np_rand_state = np.random.get_state()
cls._py_rand_state = random.getstate()
cls.call_once = False
cls.dtype = None
cls.outputs = {}
cls.input_shape_is_large = True
cls.is_calc_ref = False
cls.check_prim = False
np.random.seed(123)
random.seed(124)
if paddle.is_compiled_with_npu():
cls._use_system_allocator = _set_use_system_allocator(False)
else:
cls._use_system_allocator = _set_use_system_allocator(True)
@classmethod
def tearDownClass(cls):
"""Restore random seeds"""
np.random.set_state(cls._np_rand_state)
random.setstate(cls._py_rand_state)
_set_use_system_allocator(cls._use_system_allocator)
if hasattr(cls, 'check_prim') and os.getenv('FLAGS_prim_test_log'):
print("check prim end!")
def is_empty_grad_op(op_type):
all_op_kernels = core._get_all_register_op_kernels()
grad_op = op_type + '_grad'
if grad_op in all_op_kernels.keys():
if is_mkldnn_op_test():
grad_op_kernels = all_op_kernels[grad_op]
for grad_op_kernel in grad_op_kernels:
if 'MKLDNN' in grad_op_kernel:
return False
else:
return False
return True
def is_xpu_op_test():
return hasattr(cls, "use_xpu") and cls.use_xpu
def is_mkldnn_op_test():
return hasattr(cls, "use_mkldnn") and cls.use_mkldnn
def is_rocm_op_test():
return core.is_compiled_with_rocm()
def is_npu_op_test():
return hasattr(cls, "use_npu") and cls.use_npu
def is_mlu_op_test():
return hasattr(cls, "use_mlu") and cls.use_mlu
def is_custom_device_op_test():
return hasattr(cls, "use_custom_device") and cls.use_custom_device
if not hasattr(cls, "op_type"):
raise AssertionError(
"This test do not have op_type in class attrs, "
"please set self.__class__.op_type=the_real_op_type manually."
)
# case in NO_FP64_CHECK_GRAD_CASES and op in NO_FP64_CHECK_GRAD_OP_LIST should be fixed
if not hasattr(cls, "no_need_check_grad") and not is_empty_grad_op(
cls.op_type
):
if cls.dtype is None or (
cls.dtype == np.float16
and cls.op_type
not in op_accuracy_white_list.NO_FP16_CHECK_GRAD_OP_LIST
and not hasattr(cls, "exist_check_grad")
):
raise AssertionError(
"This test of %s op needs check_grad." % cls.op_type
)
# check for op test with fp64 precision, but not check mkldnn op test for now
if (
cls.dtype in [np.float32, np.float64]
and cls.op_type
not in op_accuracy_white_list.NO_FP64_CHECK_GRAD_OP_LIST
and not hasattr(cls, 'exist_fp64_check_grad')
and not is_xpu_op_test()
and not is_mkldnn_op_test()
and not is_rocm_op_test()
and not is_npu_op_test()
and not is_mlu_op_test()
and not is_custom_device_op_test()
and not cls.check_prim
):
raise AssertionError(
"This test of %s op needs check_grad with fp64 precision."
% cls.op_type
)
if (
not cls.input_shape_is_large
and cls.op_type
not in check_shape_white_list.NEED_TO_FIX_OP_LIST
):
raise AssertionError(
"Input's shape should be large than or equal to 100 for "
+ cls.op_type
+ " Op."
)
def try_call_once(self, data_type):
if not self.call_once:
self.call_once = True
self.dtype = data_type
def is_bfloat16_op(self):
# self.dtype is the dtype of inputs, and is set in infer_dtype_from_inputs_outputs.
# Make sure this function is called after calling infer_dtype_from_inputs_outputs.
return (
self.dtype == np.uint16
or (
hasattr(self, 'output_dtype') and self.output_dtype == np.uint16
)
or (
hasattr(self, 'mkldnn_data_type')
and self.mkldnn_data_type == "bfloat16"
)
or (
hasattr(self, 'attrs')
and 'mkldnn_data_type' in self.attrs
and self.attrs['mkldnn_data_type'] == 'bfloat16'
)
)
def is_float16_op(self):
# self.dtype is the dtype of inputs, and is set in infer_dtype_from_inputs_outputs.
# Make sure this function is called after calling infer_dtype_from_inputs_outputs.
return (
self.dtype == np.float16
or self.dtype == "float16"
or (
hasattr(self, 'output_dtype')
and self.output_dtype == np.float16
)
or (
hasattr(self, 'mkldnn_data_type')
and self.mkldnn_data_type == "float16"
)
or (
hasattr(self, 'attrs')
and 'mkldnn_data_type' in self.attrs
and self.attrs['mkldnn_data_type'] == 'float16'
)
)
def is_mkldnn_op(self):
return (hasattr(self, "use_mkldnn") and self.use_mkldnn) or (
hasattr(self, "attrs")
and "use_mkldnn" in self.attrs
and self.attrs["use_mkldnn"]
)
def is_xpu_op(self):
return (hasattr(self, "use_xpu") and self.use_xpu) or (
hasattr(self, "attrs")
and "use_xpu" in self.attrs
and self.attrs["use_xpu"]
)
def is_fp16_compared_with_fp32(self):
return self.is_float16_op() and (
self.op_type
not in op_accuracy_white_list.NO_FP16_COMPARED_WITH_FP32_OP_LIST
)
def enable_cal_ref_output(self):
self.is_calc_ref = self.is_fp16_compared_with_fp32()
def disable_cal_ref_output(self):
self.is_calc_ref = False
# set the self.output_dtype .
def infer_dtype_from_inputs_outputs(self, inputs, outputs):
def is_np_data(input):
return isinstance(input, (np.ndarray, np.generic))
def infer_dtype(numpy_dict, dtype_set):
assert isinstance(
numpy_dict, dict
), "self.inputs, self.outputs must be numpy_dict"
# the inputs are as follows:
# case 1: inputs = {'X': x}
# case 2: inputs = {'X': (x, x_lod)}
# case 3: inputs = {"X": [("x0", x0), ("x1", x1), ("x2", x2)]}
# case 4: inputs = {'X': [("x1", (x1, [x1_lod1])), ("x2", (x2, [x2_.lod2]))]}
# TODO(juncaipeng) infer dtype from inputs maybe obtain wrong type.
for _, var_value in numpy_dict.items():
if is_np_data(var_value): # case 1
dtype_set.add(var_value.dtype)
elif isinstance(var_value, (list, tuple)): # case 2, 3, 4
for sub_val_value in var_value:
if is_np_data(sub_val_value): # case 2
dtype_set.add(sub_val_value.dtype)
elif len(sub_val_value) > 1 and is_np_data(
sub_val_value[1]
): # case 3
dtype_set.add(sub_val_value[1].dtype)
elif (
len(sub_val_value) > 1
and isinstance(sub_val_value[1], (list, tuple))
and is_np_data(sub_val_value[1][0])
): # case 4
dtype_set.add(sub_val_value[1][0].dtype)
# infer dtype from inputs, and dtype means the precision of the test
# collect dtype of all inputs
input_dtype_set = set()
infer_dtype(inputs, input_dtype_set)
dtype_list = [
np.dtype(np.float64),
np.dtype(np.float32),
np.dtype(np.float16),
np.dtype(np.int64),
np.dtype(np.int32),
np.dtype(np.uint16),
np.dtype(np.int16),
np.dtype(np.int8),
np.dtype(np.uint8),
np.dtype(np.bool_),
]
# check the dtype in dtype_list in order, select the first dtype that in dtype_set
for dtype in dtype_list:
if dtype in input_dtype_set:
self.dtype = dtype
break
# save input dtype in class attr
self.__class__.dtype = self.dtype
# infer dtype of outputs
output_dtype_set = set()
infer_dtype(outputs, output_dtype_set)
for dtype in dtype_list:
if dtype in output_dtype_set:
self.output_dtype = dtype
break
def feed_var(self, input_vars, place):
feed_map = {}
for var_name in input_vars:
if isinstance(input_vars[var_name], list):
for name, np_value in self.inputs[var_name]:
tensor = core.LoDTensor()
if isinstance(np_value, tuple):
tensor.set(np_value[0], place)
dtype = np.array(np_value[1]).dtype
if self.is_calc_ref and dtype == np.float16:
if isinstance(np_value[1], list):
tensor.set_recursive_sequence_lengths(
np.array(np_value[1]).astype(np.float32)
)
else:
tensor.set_recursive_sequence_lengths(
np_value[1].astype(np.float32)
)
else:
tensor.set_recursive_sequence_lengths(np_value[1])
else:
if self.is_calc_ref and np_value.dtype == np.float16:
tensor.set(np_value.astype(np.float32), place)
else:
tensor.set(np_value, place)
feed_map[name] = tensor
else:
tensor = core.LoDTensor()
if isinstance(self.inputs[var_name], tuple):
tensor.set(self.inputs[var_name][0], place)
if (
self.is_calc_ref
and self.inputs[var_name][1].dtype == np.float16
):
tensor.set_recursive_sequence_lengths(
self.inputs[var_name][1].astype(np.float32)
)
else:
tensor.set_recursive_sequence_lengths(
self.inputs[var_name][1]
)
else:
if (
self.is_calc_ref
and self.inputs[var_name].dtype == np.float16
):
tensor.set(
self.inputs[var_name].astype(np.float32), place
)
else:
tensor.set(self.inputs[var_name], place)
feed_map[var_name] = tensor
return feed_map
def _append_ops(self, block):
self.__class__.op_type = (
self.op_type
) # for ci check, please not delete it for now
if self.is_mkldnn_op():
self.__class__.use_mkldnn = True
if self.is_xpu_op():
self.__class__.use_xpu = True
op_proto = OpProtoHolder.instance().get_op_proto(self.op_type)
"infer datatype from inputs and outputs for this test case"
if self.is_bfloat16_op():
self.dtype = np.uint16
self.__class__.dtype = self.dtype
self.output_dtype = np.uint16
else:
self.infer_dtype_from_inputs_outputs(self.inputs, self.outputs)
inputs = append_input_output(
block, op_proto, self.inputs, True, self.dtype, self.is_calc_ref
)
outputs = append_input_output(
block, op_proto, self.outputs, False, self.dtype, self.is_calc_ref
)
if hasattr(self, "cache_name_list"):
for name in self.cache_name_list:
inputs[name] = block.create_var(
name=name,
persistable=True,
type=core.VarDesc.VarType.RAW,
stop_gradient=True,
)
op = block.append_op(
type=self.op_type,
inputs=inputs,
outputs=outputs,
attrs=copy(self.attrs) if hasattr(self, "attrs") else {},
)
# infer variable type and infer shape in compile-time
op.desc.infer_var_type(block.desc)
op.desc.infer_shape(block.desc)
return op
def _get_io_vars(self, block, numpy_inputs):
inputs = {}
for name, value in numpy_inputs.items():
if isinstance(value, list):
var_list = [
block.var(sub_name) for sub_name, sub_value in value
]
inputs[name] = var_list
else:
inputs[name] = block.var(name)
return inputs
def _get_inputs(self, block):
return self._get_io_vars(block, self.inputs)
def _get_outputs(self, block):
return self._get_io_vars(block, self.outputs)
def calc_output(self, place):
outs, _ = self._calc_output(place)
return outs
def _create_var_from_numpy(self, value):
if isinstance(value, tuple):
data = value[0]
lod = value[1]
v = fluid.dygraph.base.to_variable(value=data)
v.value().get_tensor().set_recursive_sequence_lengths(lod)
return v
else:
return fluid.dygraph.base.to_variable(value)
def get_sequence_batch_size_1_input(self, lod=None, shape=None):
"""Get LoD input data whose batch size is 1.
All sequence related OP unittests should call this function to contain the case of batch size = 1.
Args:
lod (list[list of int], optional): Length-based LoD, length of lod[0] should be 1. Default: [[13]].
shape (list, optional): Shape of input, shape[0] should be equals to lod[0][0]. Default: [13, 23].
Returns:
tuple (ndarray, lod) : LoD input data whose batch size is 1.
"""
if lod is None:
lod = [[13]]
if shape is None:
shape = [13, 23]
assert len(lod[0]) == 1
assert lod[0][0] == shape[0]
x = np.random.uniform(0.1, 1, shape).astype('float32')
return (x, lod)
def lod_has_single_zero(self, lod):
for i in range(len(lod) - 2):
if lod[i] != 0 and lod[i + 1] == 0 and lod[i + 2] != 0:
return True
return False
def lod_has_continuous_zero(self, lod):
for i in range(len(lod) - 3):
if (
lod[i] != 0
and lod[i + 1] == 0
and lod[i + 2] == 0
and lod[i + 3] != 0
):
return True
return False
def get_sequence_instance_size_0_input(self, lod=None, shape=None):
"""Get LoD input data whose instance size is 0.
All sequence related OP unittests should call this function to contain the case of instance size is 0.
Args:
lod (list[list of int], optional): Length-based LoD, lod[0]'s size must at least eight, lod[0] must at least two zeros at the beginning and at least two zeros at the end, the middle position of lod[0] contains a single zero and multiple zero. Default: [[0, 0, 4, 0, 3, 0, 0, 5, 0, 0]].
shape (list, optional): Shape of input, shape[0] should be equals to lod[0][0]. Default: [13, 23].
Returns:
tuple (ndarray, lod): LoD input data whose instance size is 0.
"""
if lod is None:
lod = [[0, 0, 4, 0, 3, 0, 0, 5, 0, 0]]
if shape is None:
shape = [12, 10]
assert len(lod[0]) >= 8
assert (
lod[0][0] == 0
and lod[0][1] == 0
and lod[0][-1] == 0
and lod[0][-2] == 0
)
assert self.lod_has_single_zero(lod[0]) is True
assert self.lod_has_continuous_zero(lod[0]) is True
assert sum(lod[0]) == shape[0]
x = np.random.uniform(0.1, 1, shape).astype('float32')
return (x, lod)
def append_input_output_for_dygraph(
self, op_proto, np_list, is_input, if_return_inputs_grad_dict, block
):
def create_var(
np_value,
name,
is_input,
if_return_inputs_grad_dict,
is_calc_ref=False,
):
np_value_temp = np_value
has_lod = False
lod_temp = None
if isinstance(np_value, tuple):
np_value_temp = np_value[0]
has_lod = True
lod_temp = np_value[1]
if is_input:
if is_calc_ref and np_value_temp.dtype == np.float16:
v = self._create_var_from_numpy(
np_value_temp.astype(np.float32)
)
else:
v = self._create_var_from_numpy(np_value_temp)
if if_return_inputs_grad_dict:
v.stop_gradient = False
if hasattr(v, "retain_grads"):
v.retain_grads()
if has_lod:
v.value().get_tensor().set_recursive_sequence_lengths(
lod_temp
)
else:
if is_calc_ref and np_value_temp.dtype == np.float16:
v = block.create_var(
name=name,
dtype=np.float32,
type=core.VarDesc.VarType.LOD_TENSOR,
persistable=False,
stop_gradient=False,
)
else:
v = block.create_var(
name=name,
dtype=np_value_temp.dtype,
type=core.VarDesc.VarType.LOD_TENSOR,
persistable=False,
stop_gradient=False,
)
return v
# prepare variable for input or output
var_dict = defaultdict(list)
if if_return_inputs_grad_dict:
inputs_grad_dict = defaultdict()
proto_list = op_proto.inputs if is_input else op_proto.outputs
for var_proto in proto_list:
name = var_proto.name
if (name not in np_list) and var_proto.dispensable:
continue
if name not in np_list:
assert var_proto.intermediate, "{} not found".format(name)
v = block.create_var(
dtype='float32', type=core.VarDesc.VarType.LOD_TENSOR
)
var_dict[name].append(v)
if if_return_inputs_grad_dict:
inputs_grad_dict[name] = v
continue
if var_proto.duplicable:
assert isinstance(
np_list[name], list
), "Duplicable {} should be set as list".format(name)
var_list = []
slot_name = name
for (name, np_value) in np_list[slot_name]:
v = create_var(
np_value,
name,
is_input,
if_return_inputs_grad_dict,
self.is_calc_ref,
)
var_list.append(v)
if if_return_inputs_grad_dict:
inputs_grad_dict[name] = v
var_dict[slot_name] = var_list
else:
nplist_value_temp = None
name_temp = None
if isinstance(np_list[name], list):
nplist_value_temp = np_list[name][0]
name_temp = name
else:
nplist_value_temp = np_list[name]
name_temp = unique_name.generate("%s_out" % (name))
v = create_var(
nplist_value_temp,
name_temp,
is_input,
if_return_inputs_grad_dict,
self.is_calc_ref,
)
var_dict[name].append(v)
if if_return_inputs_grad_dict:
inputs_grad_dict[name] = v
if if_return_inputs_grad_dict:
return var_dict, inputs_grad_dict
else:
return var_dict
def _check_api_outs_by_dygraph_outs(self, api_outs, dygraph_outs, place):
"""for quick verify, here we take a simplest strategy:
1. we only check variable in api_outs.
2. we simply check the numpy (tensor) .
3. we set atol and rtol as 1e-5, because they are unrelated to dtype.
"""
for name in api_outs:
np_api = np.array(api_outs[name])
np_dyg = np.array(dygraph_outs[name])
np.testing.assert_allclose(
np_api,
np_dyg,
rtol=1e-05,
equal_nan=False,
err_msg='Output ('
+ name
+ ') has diff at '
+ str(place)
+ '\nExpect '
+ str(np_dyg)
+ '\n'
+ 'But Got'
+ str(np_api)
+ ' in class '
+ self.__class__.__name__,
)
def _calc_python_api_output(self, place, egr_inps=None, egr_oups=None):
"""set egr_inps and egr_oups = None if you want to create it by yourself."""
def construct_output_dict_by_kernel_sig(ret_tuple, output_sig):
if hasattr(self, "python_out_sig"):
output_sig = self.python_out_sig
if not isinstance(ret_tuple, (tuple, list)):
ret_tuple = [ret_tuple]
if len(output_sig) == len(ret_tuple):
# [assumption]: we assume {"Out": [Tensor]}
return {a: [b] for a, b in zip(output_sig, ret_tuple)}
else:
# [assumption]: return multi-Tensor in a single output. such as paddle.split()
assert (
len(output_sig) == 1
), "Don't support multi-output with multi-tensor output. (May be you can use set `python_out_sig`, see `test_squeeze2_op` as a example.)"
return {output_sig[0]: ret_tuple}
def cal_python_api(python_api, args, kernel_sig):
inputs_sig, attrs_sig, outputs_sig = kernel_sig
args = OpTestUtils.assumption_assert_and_transform(
args, len(inputs_sig)
)
ret_tuple = python_api(*args)
return construct_output_dict_by_kernel_sig(ret_tuple, outputs_sig)
with fluid.dygraph.base.guard(place=place):
block = fluid.default_main_program().global_block()
op_proto = OpProtoHolder.instance().get_op_proto(self.op_type)
# prepare input variable
eager_tensor_inputs = (
egr_inps
if egr_inps
else self.append_input_output_for_dygraph(
op_proto, self.inputs, True, False, block
)
)
# prepare output variable
eager_tensor_outputs = (
egr_oups
if egr_oups
else self.append_input_output_for_dygraph(
op_proto, self.outputs, False, False, block
)
)
# prepare attributes
attrs_outputs = {}
if hasattr(self, "attrs"):
for attrs_name in self.attrs:
if self.attrs[attrs_name] is not None:
attrs_outputs[attrs_name] = self.attrs[attrs_name]
kernel_sig = OpTestUtils._get_kernel_signature(
self.op_type,
eager_tensor_inputs,
eager_tensor_outputs,
canonicalize_attrs(attrs_outputs, op_proto),
)
if not kernel_sig:
return None
assert hasattr(self, "python_api"), (
"Detect there is KernelSignature for `%s` op, please set the `self.python_api` if you set check_eager = True"
% self.op_type
)
args = OpTestUtils.prepare_python_api_arguments(
self.python_api,
eager_tensor_inputs,
attrs_outputs,
kernel_sig,
)
""" we directly return the cal_python_api value because the value is already tensor.
"""
return cal_python_api(self.python_api, args, kernel_sig)
def _calc_dygraph_output(self, place, parallel=False, no_check_set=None):
self.__class__.op_type = (
self.op_type
) # for ci check, please not delete it for now
with fluid.dygraph.base.guard(place=place):
block = fluid.default_main_program().global_block()
op_proto = OpProtoHolder.instance().get_op_proto(self.op_type)
# prepare input variable
inputs = self.append_input_output_for_dygraph(
op_proto, self.inputs, True, False, block
)
# prepare output variable
outputs = self.append_input_output_for_dygraph(
op_proto, self.outputs, False, False, block
)
# prepare attributes
attrs_outputs = {}
if hasattr(self, "attrs"):
for attrs_name in self.attrs:
if self.attrs[attrs_name] is not None:
attrs_outputs[attrs_name] = self.attrs[attrs_name]
block.append_op(
type=self.op_type,
inputs=inputs,
outputs=outputs,
attrs=attrs_outputs if hasattr(self, "attrs") else None,
)
return outputs
def _calc_output(
self,
place,
parallel=False,
no_check_set=None,
loss=None,
enable_inplace=None,
for_inplace_test=None,
):
with paddle.fluid.framework._static_guard():
program = Program()
block = program.global_block()
op = self._append_ops(block)
inputs = self._get_inputs(block)
outputs = self._get_outputs(block)
feed_map = self.feed_var(inputs, place)
if for_inplace_test:
# Some variables' tensors hold no buffer (tensor's _holder is NULL), like XShape in reshape2 op,
# and the shapes of those variables contain 0 (eg. Xshape.shape = [0, 2, 5]).
# Set persistable for those variables in order to get them from global_scope for inplace grad test directly other than feed them,
# since feed op calls check_memory_size() which fails when tensor's holder_ is NULL.
for out_name in op.output_arg_names:
var = block.var(out_name)
if 0 in var.shape:
var.persistable = True
original_program = program
if parallel:
use_cuda = False
if isinstance(place, fluid.CUDAPlace):
use_cuda = True
compiled_prog = fluid.CompiledProgram(program)
program = compiled_prog
fetch_list = getattr(self, "fetch_list", [])
# if the fetch_list is customized by user, we use it directly.
# if not, fill the fetch_list by the user configured outputs in test.
if len(fetch_list) == 0:
for var_name, var in outputs.items():
if no_check_set is not None and var_name in no_check_set:
continue
if isinstance(var, list):
for v in var:
fetch_list.append(v.name)
else:
fetch_list.append(var.name)
# if the fetch_list still empty, fill the fetch_list by the operator output.
if len(fetch_list) == 0:
for out_name, out_dup in Operator.get_op_outputs(self.op_type):
fetch_list.append(str(out_name))
if enable_inplace is not None:
build_strategy = fluid.BuildStrategy()
build_strategy.enable_inplace = enable_inplace
compiled_prog = fluid.CompiledProgram(
program, build_strategy=build_strategy
)
program = compiled_prog
executor = Executor(place)
outs = executor.run(
program,
feed=feed_map,
fetch_list=fetch_list,
return_numpy=False,
)
self.op = op
self.program = original_program
if for_inplace_test:
return outs, fetch_list, feed_map, original_program, op.desc
else:
return outs, fetch_list
def _compare_expect_and_actual_outputs(
self, place, fetch_list, expect_outs, actual_outs, inplace_atol=None
):
"""Compare expect outs and actual outs of an tested op.
Args:
place (CPUPlace | CUDAPlace): The place where the op runs.
fetch_list (list): The outputs of tested op.
expect_outs (list): The expect outs of tested op.
actual_outs (list): The actual outs of tested op.
inplace_atol (float): The tolerable error, only set when tested op doesn't ensure computational consistency, like group_norm op.
Returns:
None.
"""
# compare expect_outs and actual_outs
for i, name in enumerate(fetch_list):
# Note(zhiqiu): inplace_atol should be only set when op doesn't ensure
# computational consistency.
# When inplace_atol is not None, the inplace check uses numpy.allclose
# to check inplace result instead of numpy.array_equal.
expect_out = np.array(expect_outs[i])
actual_out = np.array(actual_outs[i])
if inplace_atol is not None:
np.testing.assert_allclose(
expect_out,
actual_out,
rtol=1e-05,
atol=inplace_atol,
err_msg='Output ('
+ name
+ ') has diff at '
+ str(place)
+ ' when using and not using inplace'
+ '\nExpect '
+ str(expect_out)
+ '\n'
+ 'But Got'
+ str(actual_out)
+ ' in class '
+ self.__class__.__name__,
)
else:
np.testing.assert_array_equal(
expect_out,
actual_out,
err_msg='Output ('
+ name
+ ') has diff at '
+ str(place)
+ ' when using and not using inplace'
+ '\nExpect '
+ str(expect_out)
+ '\n'
+ 'But Got'
+ str(actual_out)
+ ' in class '
+ self.__class__.__name__
+ '\n',
)
def _construct_grad_program_from_forward(
self, fwd_program, grad_op_desc, op_grad_to_var
):
"""Generate grad_program which contains the grad_op.
Args:
fwd_program (tuple): The program that contains grad_op_desc's corresponding forward op.
grad_op_desc (OpDesc): The OpDesc of grad op.
op_grad_to_var (dict): The relation of variables in grad op and its forward op.
Returns:
grad_program (program): The program which contains the grad_op.
"""
grad_program = Program()
grad_block = grad_program.global_block()
new_op_desc = grad_block.desc.append_op()
new_op_desc.copy_from(grad_op_desc)
grad_program._sync_with_cpp()
# Create grad vars based on fwd vars (shape and dtype)
for arg in (
grad_op_desc.input_arg_names() + grad_op_desc.output_arg_names()
):
fwd_var_name = op_grad_to_var.get(arg, None)
if fwd_var_name is None:
fwd_var_name = arg
fwd_var = fwd_program.global_block().vars.get(fwd_var_name)
assert fwd_var is not None, "{} cannot be found".format(
fwd_var_name
)
grad_var = grad_block.create_var(
name=arg,
dtype=fwd_var.dtype,
shape=fwd_var.shape,
type=fwd_var.type,
persistable=False,
)
# Some variables' tensors hold no buffer (tensor's _holder is NULL), like XShape in reshape2 op,
# and the shapes of those variables contain 0 (eg. Xshape.shape = [0, 2, 5]).
# Set persistable for those variables in order to get them from global_scope for inplace grad test directly other than feed them,
# since feed op calls check_memory_size() which fails when tensor's holder_ is NULL.
if 0 in grad_var.shape:
grad_var.persistable = True
grad_program._sync_with_cpp()
return grad_program
def _construct_grad_feed_map_from_forward(
self, place, fwd_res, grad_op_desc, op_grad_to_var
):
"""Generate grad_feed_map for grad_program.
since we don`t really check gradient accuracy, but check the consistency when using and not using inplace,
we use fwd outs (also inputs sometimes) to construct grad inputs.
Args:
place (CPUPlace | CUDAPlace): The place where the op runs.
fwd_res (tuple): The outputs of its forward op, in the same form as returns of _calc_outputs() when for_inplace_test is True.
i.e., tuple(fwd_outs, fwd_fetch_list, fwd_feed_map, fwd_program, fwd_op_desc)
grad_op_desc (OpDesc): The OpDesc of grad op.
op_grad_to_var (dict): The relation of variables in grad op and its fwd_op.
Returns:
grad_feed_map (dict): The feed_map of grad_op.
"""
(
fwd_outs,
fwd_fetch_list,
fwd_feed_map,
fwd_program,
fwd_op_desc,
) = fwd_res
p = core.Place()
p.set_place(place)
grad_feed_map = {}
for arg in grad_op_desc.input_arg_names():
if arg in fwd_feed_map.keys():
grad_feed_map[arg] = fwd_feed_map[arg]._copy(p)
else:
fwd_var_name = op_grad_to_var.get(arg, None)
if fwd_var_name is None:
fwd_var_name = arg
for i, out_name in enumerate(fwd_fetch_list):
if out_name == fwd_var_name:
# don't feed variables whose tensors hold no buffer (shape contains 0 like shape = [0,2,5] and holder_ is NULL), like XShape in reshape2 op.
# get them from global_scope directly since we have set them persistable in fwd execution
if 0 in fwd_program.global_block().var(out_name).shape:
continue
else:
grad_feed_map[arg] = fwd_outs[i]._copy(p)
return grad_feed_map
def _get_need_run_ops(self, op_desc, fwd_op_desc=None):
"""Postorder traversal of the 'grad' tree to get all ops that need to run during inplace test.
An op needs to run druing inplace check if,
(1) it has infer_inplace,
(2) it has infer_inplace in its grad descendants. (since we need its outputs as to construct its grad's inputs)
Args:
op_desc (OpDesc): The op_desc of current op.
fwd_op_desc (OpDesc): The op_desc of current op's forward op, None if current op has no forward op.
Eg. relu's fwd_op is None, relu_grad's fwd_op is relu, relu_grad_grad's fwd_op is relu_grad, etc.
Returns:
need_run_ops (list[(op_desc, fwd_op_desc)]): The ops that need to run during inplace test.
"""
need_run_ops = []
visited_ops = []
def _dfs_grad_op(op_desc, fwd_op_desc=None):
visited_ops.append(op_desc.type())
has_infer_inplace = fluid.core.has_infer_inplace(op_desc.type())
has_grad_op_maker = fluid.core.has_grad_op_maker(op_desc.type())
has_infer_inplace_in_grad_descendants = False
if not has_grad_op_maker:
has_infer_inplace_in_descendants = False
else:
# get grad_op_desc
grad_op_desc_list, op_grad_to_var = core.get_grad_op_desc(
op_desc, set(), []
)
if not grad_op_desc_list:
has_infer_inplace_in_grad_descendants = False
else:
for i, grad_op_desc in enumerate(grad_op_desc_list):
if (
grad_op_desc.type() not in visited_ops
and _dfs_grad_op(grad_op_desc, fwd_op_desc=op_desc)
):
has_infer_inplace_in_grad_descendants = True
if has_infer_inplace or has_infer_inplace_in_grad_descendants:
need_run_ops.append((op_desc, fwd_op_desc))
return True
else:
return False
_dfs_grad_op(op_desc, fwd_op_desc=fwd_op_desc)
return need_run_ops
def _check_forward_inplace(
self, place, no_check_set=None, inplace_atol=None
):
"""Check the inplace correctness of given op (self.op_type).
Run the op twice with same inputs, one enable inplace and another disable, compare their outputs.
Args:
place (CPUPlace | CUDAPlace): The place where the op runs.
no_check_set (list): The names of outputs that needn't check, like XShape of reshape op.
inplace_atol (float): The tolerable error, only set when op doesn't ensure computational consistency, like group_norm op.
Returns:
expect_res (tuple(outs, fetch_list, feed_map, program, op_desc)): The results of given op.
We return this to construct grad_program and grad_feed_map for grad inplace check.
"""
# _calc_output() returns in the form tuple(outs, fetch_list, feed_map, program, op_desc) when for_inplace_test=True.
expect_res = self._calc_output(
place,
no_check_set=no_check_set,
enable_inplace=False,
for_inplace_test=True,
)
actual_res = self._calc_output(
place,
no_check_set=no_check_set,
enable_inplace=True,
for_inplace_test=True,
)
# compare expect_outs and actual_outs
self._compare_expect_and_actual_outputs(
place,
expect_res[1],
expect_res[0],
actual_res[0],
inplace_atol=inplace_atol,
)
return expect_res
def _calc_grad_output(
self, place, fwd_res, grad_op_desc, enable_inplace=None
):
"""Calculate grad_output for given grad_op_desc.
since we don`t really check gradient accuracy, but check the consistency when using and not using inplace,
we use fwd outs (also inputs sometimes) to construct grad inputs.
Args:
place (CPUPlace | CUDAPlace): The place where the op runs.
fwd_res (tuple): The outputs of its forward op, in the same form as returns of _calc_outputs() when for_inplace_test is True.
i.e., tuple(fwd_outs, fwd_fetch_list, fwd_feed_map, fwd_program, fwd_op_desc).
grad_op_desc (OpDesc): The OpDesc of grad op.
enable_inplace (bool): Enable inplace or not.
Returns:
res (tuple(outs, fetch_list, feed_map, program, op_desc)): The results of given grad_op_desc.
"""
with paddle.fluid.framework._static_guard():
(
fwd_outs,
fwd_fetch_list,
fwd_feed_map,
fwd_program,
fwd_op_desc,
) = fwd_res
grad_op_desc_list, op_grad_to_var = core.get_grad_op_desc(
fwd_op_desc, set(), []
)
grad_program = self._construct_grad_program_from_forward(
fwd_program, grad_op_desc, op_grad_to_var
)
grad_feed_map = self._construct_grad_feed_map_from_forward(
place, fwd_res, grad_op_desc, op_grad_to_var
)
grad_fetch_list = grad_op_desc.output_arg_names()
exe = Executor(place)
program = grad_program
if enable_inplace is not None:
build_strategy = fluid.BuildStrategy()
build_strategy.enable_inplace = enable_inplace
compiled_program = fluid.CompiledProgram(
grad_program, build_strategy=build_strategy
)
program = compiled_program
outs = exe.run(
program,
feed=grad_feed_map,
fetch_list=grad_fetch_list,
return_numpy=False,
)
return outs, grad_fetch_list, grad_feed_map, grad_program, grad_op_desc
def _check_grad_inplace(
self, place, fwd_res, grad_op_desc, inplace_atol=None
):
"""Check the inplace correctness of given grad_op_desc.
Run the grad op twice with same inputs, one enable inplace and another disable, compare their outputs.
It works like _check_forward_inplace, but the way to construct program and feed_map differs.
So we define a new function for grad, grad_grad, etc.
Args:
place (CPUPlace | CUDAPlace): The place where the op runs.
fwd_res (tuple): The outputs of its forward op, in the same form as returns of _calc_outputs() when for_inplace_test is True.
i.e., tuple(fwd_outs, fwd_fetch_list, fwd_feed_map, fwd_program, fwd_op_desc).
grad_op_desc (OpDesc): The OpDesc of grad op.
inplace_atol (float): The tolerable error, only set when op doesn't ensure computational consistency, like group_norm op.
Returns:
expect_res (tuple(outs, fetch_list, feed_map, program, op_desc)): The results of given op.
We return this to construct grad_program and grad_feed_map for grad inplace check.
"""
expect_res = self._calc_grad_output(
place, fwd_res, grad_op_desc, enable_inplace=False
)
actual_res = self._calc_grad_output(
place, fwd_res, grad_op_desc, enable_inplace=True
)
self._compare_expect_and_actual_outputs(
place,
expect_res[1],
expect_res[0],
actual_res[0],
inplace_atol=inplace_atol,
)
return expect_res
def check_inplace_output_with_place(
self, place, no_check_set=None, inplace_atol=None
):
"""Chech the inplace correctness of given op, its grad op, its grad_grad op, etc.
(1) Get all ops need to run. (see conditions in _get_need_run_ops())
(2) Run op in need_run_ops, and do inplace check if it has infer_inplace.
Args:
place (CPUPlace | CUDAPlace): The place where the op runs.
no_check_set (list): The names of outputs that needn't check, like XShape of reshape op.
inplace_atol (float): The tolerable error, only set when op doesn't ensure computational consistency, like group_norm op.
Returns:
None
"""
if getattr(self, "no_need_check_inplace", False):
return
has_infer_inplace = fluid.core.has_infer_inplace(self.op_type)
has_grad_op_maker = fluid.core.has_grad_op_maker(self.op_type)
fwd_res = self._calc_output(
place, no_check_set=no_check_set, for_inplace_test=True
)
op_desc = fwd_res[4]
need_run_ops = self._get_need_run_ops(op_desc)
res = {}
if hasattr(self, 'attrs') and bool(self.attrs.get('use_xpu', False)):
return
for op_desc, father_op_desc in reversed(need_run_ops):
# The first one is the forward op
has_infer_inplace = fluid.core.has_infer_inplace(op_desc.type())
if op_desc.type() == self.op_type:
if has_infer_inplace:
res[op_desc] = self._check_forward_inplace(
place,
no_check_set=no_check_set,
inplace_atol=inplace_atol,
)
else:
res[op_desc] = self._calc_output(
place, no_check_set=no_check_set, for_inplace_test=True
)
else:
# TODO(zhiqiu): enhance inplace_grad test for ops (sum and activation) using mkldnn
# skip op that use_mkldnn currently
flags_use_mkldnn = fluid.core.globals()["FLAGS_use_mkldnn"]
attrs_use_mkldnn = hasattr(self, 'attrs') and bool(
self.attrs.get('use_mkldnn', False)
)
if flags_use_mkldnn or attrs_use_mkldnn:
warnings.warn(
"check inplace_grad for ops using mkldnn is not supported"
)
continue
if has_infer_inplace:
fwd_res = res[father_op_desc]
res[op_desc] = self._check_grad_inplace(
place, fwd_res, op_desc, inplace_atol=inplace_atol
)
else:
res[op_desc] = self._calc_grad_output(
place, fwd_res, op_desc
)
def check_output_with_place(
self,
place,
atol=0,
no_check_set=None,
equal_nan=False,
check_dygraph=True,
inplace_atol=None,
check_eager=False,
check_prim=False,
):
core._set_prim_all_enabled(False)
if check_prim:
prim_checker = PrimForwardChecker(self, place)
prim_checker.check()
# Support operators which not in the NO_FP64_CHECK_GRAD_OP_LIST list can be test prim with fp32
self.__class__.check_prim = True
self.__class__.op_type = self.op_type
# disable legacy dygraph check when check_eager is True
if check_eager:
check_dygraph = False
def find_imperative_actual(target_name, dygraph_outs, place):
for name in dygraph_outs:
if name == target_name:
return dygraph_outs[name][0]
var_list = dygraph_outs[name]
for i, var in enumerate(var_list):
if var.name == target_name:
return dygraph_outs[name][i]
self.assertTrue(
False,
"Found failed {} {}".format(dygraph_outs.keys(), target_name),
)
def find_imperative_expect(target_name, dygraph_outs, place):
for name in dygraph_outs:
if name == target_name:
return dygraph_outs[name][0]
var_list = dygraph_outs[name]
for i, var in enumerate(var_list):
if var.name == target_name:
return dygraph_outs[name][i]
self.assertTrue(
False,
"Found failed {} {}".format(dygraph_outs.keys(), target_name),
)
def find_actual(target_name, fetch_list):
found = [
i
for i, var_name in enumerate(fetch_list)
if var_name == target_name
]
self.assertTrue(
len(found) == 1, "Found {} {}".format(len(found), target_name)
)
return found[0]
def find_expect(target_name, fetch_list):
found = [
i
for i, var_name in enumerate(fetch_list)
if var_name == target_name
]
self.assertTrue(
len(found) == 1, "Found {} {}".format(len(found), target_name)
)
return found[0]
class Checker:
"""base class for check with self.outputs.
currently don't support check between checkers.
"""
def __init__(self, op_test, expect_dict):
"""expect_dict is the self.outputs
support : {str: [numpy]} and {str: [(str, numpy), (str, numpy)]}
"""
self.expects = expect_dict
self.checker_name = "checker"
self.op_test = op_test # stop the op_test object.
self.op_type = op_test.op_type
def init(self):
pass
def convert_uint16_to_float(self, actual_np, expect_np):
raise NotImplementedError("base class, not implement!")
def calculate_output(self):
"""
judge whether convert current output and expect to uint16.
return True | False
"""
def _is_skip_name(self, name):
if name not in self.expects:
return True
if no_check_set is not None and name in no_check_set:
return True
return False
def find_actual_value(self, name):
"""return: (actual_tensor(var_base), actual_numpy)"""
raise NotImplementedError("base class, not implement!")
def find_expect_value(self, name):
"""return: (expect_tensor(var_base), actual_numpy)"""
raise NotImplementedError("base class, not implement!")
def _compare_numpy(self, name, actual_np, expect_np):
if actual_np.shape == expect_np.shape:
np.testing.assert_allclose(
actual_np,
expect_np,
atol=atol,
rtol=self.rtol if hasattr(self, 'rtol') else 1e-5,
equal_nan=equal_nan,
err_msg=(
"Output ("
+ name
+ ") has diff at "
+ str(place)
+ " in "
+ self.checker_name
),
)
return
self.op_test.assertTrue(
np.allclose(
actual_np,
expect_np,
atol=atol,
rtol=self.rtol if hasattr(self, 'rtol') else 1e-5,
equal_nan=equal_nan,
),
"Output ("
+ name
+ ") has diff at "
+ str(place)
+ " in "
+ self.checker_name,
)
def _compare_list(self, name, actual, expect):
"""if expect is a tuple, we need to compare list."""
raise NotImplementedError("base class, not implement!")
def compare_single_output_with_expect(self, name, expect):
actual, actual_np = self.find_actual_value(name)
if self.op_test.is_fp16_compared_with_fp32():
expect, expect_np = self.find_expect_value(name)
else:
expect_np = (
expect[0] if isinstance(expect, tuple) else expect
)
actual_np, expect_np = self.convert_uint16_to_float_ifneed(
actual_np, expect_np
)
# modify there for fp32 check
# NOTE(zhiqiu): np.allclose([], [1.]) returns True
# see details: https://stackoverflow.com/questions/38331703/why-does-numpys-broadcasting-sometimes-allow-comparing-arrays-of-different-leng
if expect_np.size == 0:
self.op_test.assertTrue(actual_np.size == 0)
self._compare_numpy(name, actual_np, expect_np)
if isinstance(expect, tuple):
self._compare_list(name, actual, expect)
def compare_outputs_with_expects(self):
for out_name, out_dup in Operator.get_op_outputs(self.op_type):
if self._is_skip_name(out_name):
continue
if out_dup:
# if self.output = {'name': [(subname, Tensor), (subname, Tensor)]}
sub_out = self.expects[out_name]
if not isinstance(sub_out, list):
raise AssertionError(
"sub_out type %s is not list", type(sub_out)
)
for item in sub_out:
sub_out_name, expect = item[0], item[1]
self.compare_single_output_with_expect(
sub_out_name, expect
)
else:
expect = self.expects[out_name]
self.compare_single_output_with_expect(out_name, expect)
def check(self):
"""
return None means ok, raise Error means failed.
the main enter point of Checker class
"""
self.init()
self.calculate_output()
self.compare_outputs_with_expects()
class StaticChecker(Checker):
def init(self):
self.checker_name = "static checker"
def calculate_output(self):
outs, fetch_list = self.op_test._calc_output(
place, no_check_set=no_check_set
)
self.outputs = outs
self.fetch_list = fetch_list
if self.op_test.is_fp16_compared_with_fp32():
self.op_test.enable_cal_ref_output()
ref_outs, ref_fetch_list = self.op_test._calc_output(
place, no_check_set=no_check_set
)
self.op_test.disable_cal_ref_output()
self.ref_outputs = ref_outs
self.ref_fetch_list = ref_fetch_list
def find_actual_value(self, name):
idx = find_actual(name, self.fetch_list)
actual = self.outputs[idx]
actual_t = np.array(actual)
return actual, actual_t
def find_expect_value(self, name):
idx = find_expect(name, self.ref_fetch_list)
expect = self.ref_outputs[idx]
expect_t = np.array(expect)
return expect, expect_t
def convert_uint16_to_float_ifneed(self, actual_np, expect_np):
"""
judge whether convert current output and expect to uint16.
return True | False
"""
if actual_np.dtype == np.uint16:
if expect_np.dtype in [np.float32, np.float64]:
actual_np = convert_uint16_to_float(actual_np)
self.rtol = 1.0e-2
elif actual_np.dtype == np.float16:
self.rtol = 1.0e-3
else:
self.rtol = 1.0e-5
if (
expect_np.dtype == np.uint16
and actual_np.dtype == np.uint16
):
nonlocal atol
expect_np = convert_uint16_to_float(expect_np)
actual_np = convert_uint16_to_float(actual_np)
atol = max(atol, 0.03)
return actual_np, expect_np
def _compare_list(self, name, actual, expect):
"""if expect is a tuple, we need to compare list."""
self.op_test.assertListEqual(
actual.recursive_sequence_lengths(),
expect[1],
"Output (" + name + ") has different lod at " + str(place),
)
class DygraphChecker(Checker):
def init(self):
self.checker_name = "dygraph checker"
def calculate_output(self):
self.outputs = self.op_test._calc_dygraph_output(
place, no_check_set=no_check_set
)
if self.op_test.is_fp16_compared_with_fp32():
self.op_test.enable_cal_ref_output()
self.ref_outputs = self.op_test._calc_dygraph_output(
place, no_check_set=no_check_set
)
self.op_test.disable_cal_ref_output()
def find_actual_value(self, name):
with fluid.dygraph.base.guard(place=place):
imperative_actual = find_imperative_actual(
name, self.outputs, place
)
imperative_actual_t = np.array(
imperative_actual.value().get_tensor()
)
return imperative_actual, imperative_actual_t
def find_expect_value(self, name):
with fluid.dygraph.base.guard(place=place):
imperative_expect = find_imperative_expect(
name, self.ref_outputs, place
)
imperative_expect_t = np.array(
imperative_expect.value().get_tensor()
)
return imperative_expect, imperative_expect_t
def convert_uint16_to_float_ifneed(self, actual_np, expect_np):
if actual_np.dtype == np.uint16:
self.rtol = 1.0e-2
elif actual_np.dtype == np.float16:
self.rtol = 1.0e-3
else:
self.rtol = 1.0e-5
if self.op_test.is_bfloat16_op():
if actual_np.dtype == np.uint16:
actual_np = convert_uint16_to_float(actual_np)
if expect_np.dtype == np.uint16:
expect_np = convert_uint16_to_float(expect_np)
return actual_np, expect_np
def _compare_list(self, name, actual, expect):
"""if expect is a tuple, we need to compare list."""
with fluid.dygraph.base.guard(place=place):
self.op_test.assertListEqual(
actual.value()
.get_tensor()
.recursive_sequence_lengths(),
expect[1],
"Output ("
+ name
+ ") has different lod at "
+ str(place)
+ " in dygraph mode",
)
def _compare_numpy(self, name, actual_np, expect_np):
if (
functools.reduce(lambda x, y: x * y, actual_np.shape, 1)
== 0
and functools.reduce(lambda x, y: x * y, expect_np.shape, 1)
== 0
):
pass
else:
if actual_np.shape == expect_np.shape:
np.testing.assert_allclose(
actual_np,
expect_np,
atol=atol,
rtol=self.rtol if hasattr(self, 'rtol') else 1e-5,
equal_nan=equal_nan,
err_msg=(
"Output ("
+ name
+ ") has diff at "
+ str(place)
+ " in "
+ self.checker_name
),
)
return
self.op_test.assertTrue(
np.allclose(
actual_np,
expect_np,
atol=atol,
rtol=self.rtol if hasattr(self, 'rtol') else 1e-5,
equal_nan=equal_nan,
),
"Output ("
+ name
+ ") has diff at "
+ str(place)
+ " in "
+ self.checker_name,
)
class EagerChecker(DygraphChecker):
def init(self):
self.checker_name = "eager checker"
def calculate_output(self):
# we only check end2end api when check_eager=True
with _test_eager_guard():
self.is_python_api_test = True
eager_dygraph_outs = self.op_test._calc_python_api_output(
place
)
if eager_dygraph_outs is None:
self.is_python_api_test = False
# missing KernelSignature, fall back to eager middle output.
eager_dygraph_outs = self.op_test._calc_dygraph_output(
place, no_check_set=no_check_set
)
self.outputs = eager_dygraph_outs
if self.op_test.is_fp16_compared_with_fp32():
self.op_test.enable_cal_ref_output()
with _test_eager_guard():
self.is_python_api_test = True
ref_eager_dygraph_outs = (
self.op_test._calc_python_api_output(place)
)
if ref_eager_dygraph_outs is None:
self.is_python_api_test = False
ref_eager_dygraph_outs = (
self.op_test._calc_dygraph_output(
place, no_check_set=no_check_set
)
)
self.op_test.disable_cal_ref_output()
self.ref_outputs = ref_eager_dygraph_outs
def _compare_numpy(self, name, actual_np, expect_np):
with _test_eager_guard():
super()._compare_numpy(name, actual_np, expect_np)
def convert_uint16_to_float_ifneed(self, actual_np, expect_np):
with _test_eager_guard():
return super().convert_uint16_to_float_ifneed(
actual_np, expect_np
)
def find_actual_value(self, name):
with _test_eager_guard():
return super().find_actual_value(name)
def find_expect_value(self, name):
with _test_eager_guard():
return super().find_expect_value(name)
def _compare_list(self, name, actual, expect):
"""if expect is a tuple, we need to compare list."""
with _test_eager_guard():
super()._compare_list(name, actual, expect)
def _is_skip_name(self, name):
# if in final state and kernel signature don't have name, then skip it.
if (
self.is_python_api_test
and hasattr(self.op_test, "python_out_sig")
and name not in self.op_test.python_out_sig
):
return True
return super()._is_skip_name(name)
# set some flags by the combination of arguments.
self.infer_dtype_from_inputs_outputs(self.inputs, self.outputs)
if (
self.dtype == np.float64
and self.op_type
not in op_threshold_white_list.NEED_FIX_FP64_CHECK_OUTPUT_THRESHOLD_OP_LIST
):
atol = 0
if self.is_bfloat16_op():
if self.is_mkldnn_op():
check_dygraph = False
check_eager = False
if (
hasattr(self, 'force_fp32_output')
and self.force_fp32_output
):
atol = 1e-2 if atol < 1e-2 else atol
else:
atol = 2 if atol < 2 else atol
else:
atol = 1e-2 if atol < 1e-2 else atol
if self.is_float16_op():
atol = 1e-3 if atol < 1e-3 else atol
if no_check_set is not None:
if (
self.op_type
not in no_check_set_white_list.no_check_set_white_list
):
raise AssertionError(
"no_check_set of op %s must be set to None." % self.op_type
)
static_checker = StaticChecker(self, self.outputs)
static_checker.check()
outs, fetch_list = static_checker.outputs, static_checker.fetch_list
if check_dygraph:
# always enable legacy dygraph
g_enable_legacy_dygraph()
dygraph_checker = DygraphChecker(self, self.outputs)
dygraph_checker.check()
dygraph_outs = dygraph_checker.outputs
# yield the original state
g_disable_legacy_dygraph()
if check_eager:
eager_checker = EagerChecker(self, self.outputs)
eager_checker.check()
eager_dygraph_outs = eager_checker.outputs
# Note(zhiqiu): inplace_atol should be only set when op doesn't ensure
# computational consistency.
# For example, group_norm uses AtomicAdd on CUDAPlace, which do not ensure
# computation order when multiple threads write the same address. So the
# result of group_norm is non-deterministic when datatype is float.
# When inplace_atol is not None, the inplace check uses numpy.allclose
# to check inplace result instead of numpy.array_equal.
if inplace_atol is not None:
warnings.warn(
"inplace_atol should only be set when op doesn't ensure computational consistency, please check it!"
)
# Check inplace for given op, its grad op, its grad_grad op, etc.
# No effect on original OpTest
# Currently not support ParallelExecutor on XPUPlace.
if (
not paddle.is_compiled_with_xpu()
and not paddle.is_compiled_with_npu()
and not paddle.is_compiled_with_mlu()
and not isinstance(place, core.CustomPlace)
):
self.check_inplace_output_with_place(
place, no_check_set=no_check_set, inplace_atol=inplace_atol
)
if check_eager:
assert not check_dygraph
return outs, eager_dygraph_outs, fetch_list
elif check_dygraph:
return outs, dygraph_outs, fetch_list
else:
return outs, fetch_list
def check_compile_vs_runtime(self, fetch_list, fetch_outs):
def find_fetch_index(target_name, fetch_list):
found = [
i
for i, var_name in enumerate(fetch_list)
if var_name == target_name
]
if len(found) == 0:
return -1
else:
self.assertTrue(
len(found) == 1,
"Found {} {}".format(len(found), target_name),
)
return found[0]
for name in self.op.desc.output_names():
var_names = self.op.desc.output(name)
for var_name in var_names:
i = find_fetch_index(var_name, fetch_list)
if i == -1:
# The output is dispensiable or intermediate.
break
out = fetch_outs[i]
if isinstance(out, core.LoDTensor):
lod_level_runtime = len(out.lod())
else:
if isinstance(out, core.LoDTensorArray):
warnings.warn(
"The check of LoDTensorArray's lod_level is not implemented now!"
)
lod_level_runtime = 0
var = self.program.global_block().var(var_name)
if var.type == core.VarDesc.VarType.LOD_TENSOR:
lod_level_compile = var.lod_level
else:
lod_level_compile = 0
self.assertEqual(
lod_level_compile,
lod_level_runtime,
"The lod_level of Output ("
+ name
+ ") is different between compile-time and runtime ("
+ str(lod_level_compile)
+ " vs "
+ str(lod_level_runtime)
+ ")",
)
def _get_places(self):
if self.dtype == np.float16:
if core.is_compiled_with_cuda() and core.op_support_gpu(
self.op_type
):
place = core.CUDAPlace(0)
if core.is_float16_supported(place):
return [place]
else:
return []
else:
return []
places = [fluid.CPUPlace()]
cpu_only = self._cpu_only if hasattr(self, '_cpu_only') else False
if (
core.is_compiled_with_cuda()
and core.op_support_gpu(self.op_type)
and not cpu_only
):
places.append(core.CUDAPlace(0))
return places
def check_output(
self,
atol=1e-5,
no_check_set=None,
equal_nan=False,
check_dygraph=True,
inplace_atol=None,
check_eager=False,
check_prim=False,
):
# disable legacy dygraph check when check_eager is True
if check_eager:
check_dygraph = False
self.__class__.op_type = self.op_type
if self.is_mkldnn_op():
self.__class__.use_mkldnn = True
if self.is_xpu_op():
self.__class__.use_xpu = True
places = self._get_places()
for place in places:
res = self.check_output_with_place(
place,
atol,
no_check_set,
equal_nan,
check_dygraph,
inplace_atol,
check_eager=check_eager,
check_prim=check_prim,
)
if check_eager:
assert not check_dygraph
outs, eager_dygraph_outs, fetch_list = res
elif check_dygraph:
outs, dygraph_outs, fetch_list = res
else:
outs, fetch_list = res
if (
self.op_type
not in compile_vs_runtime_white_list.COMPILE_RUN_OP_WHITE_LIST
):
self.check_compile_vs_runtime(fetch_list, outs)
def check_output_customized(self, checker, custom_place=None):
self.__class__.op_type = self.op_type
places = self._get_places()
if custom_place:
places.append(custom_place)
for place in places:
outs = self.calc_output(place)
outs = [np.array(out) for out in outs]
outs.sort(key=len)
checker(outs)
def check_output_with_place_customized(self, checker, place):
outs = self.calc_output(place)
outs = [np.array(out) for out in outs]
outs.sort(key=len)
checker(outs)
def _assert_is_close(
self,
numeric_grads,
analytic_grads,
names,
max_relative_error,
msg_prefix,
atol=1e-5,
):
for a, b, name in zip(numeric_grads, analytic_grads, names):
# Used by bfloat16 for now to solve precision problem
if self.is_bfloat16_op():
if a.size == 0:
self.assertTrue(b.size == 0)
np.testing.assert_allclose(
b,
a,
rtol=max_relative_error,
atol=atol,
equal_nan=False,
err_msg=(
"Operator %s error, %s variable %s (shape: %s, dtype: %s) max gradient diff over limit"
)
% (
self.op_type,
msg_prefix,
name,
str(a.shape),
self.dtype,
),
)
else:
# It asserts np.abs(a - b) / np.abs(a) < max_relative_error, in which
# max_relative_error is 1e-7. According to the value of np.abs(a), we
# change np.abs(a) to achieve dynamic threshold. For example, if
# the value of np.abs(a) is between 1e-10 and 1e-8, we set np.abs(a)*=1e4.
# Therefore, it asserts np.abs(a - b) / (np.abs(a)*1e4) < max_relative_error,
# which is the same as np.abs(a - b) / np.abs(a) < max_relative_error*1e4.
abs_a = np.abs(a)
if abs_a.ndim > 0:
if (
self.dtype == np.float64
and self.op_type
not in op_threshold_white_list.NEED_FIX_FP64_CHECK_GRAD_THRESHOLD_OP_LIST
):
abs_a[abs_a < 1e-10] = 1e-3
abs_a[
np.logical_and(abs_a > 1e-10, abs_a <= 1e-8)
] *= 1e4
abs_a[
np.logical_and(abs_a > 1e-8, abs_a <= 1e-6)
] *= 1e2
elif self.is_bfloat16_op():
abs_a[abs_a < 1e-2] = 1
else:
abs_a[abs_a < 1e-3] = 1
elif abs_a.ndim == 0:
if (
self.dtype == np.float64
and self.op_type
not in op_threshold_white_list.NEED_FIX_FP64_CHECK_GRAD_THRESHOLD_OP_LIST
):
if abs_a < 1e-10:
abs_a = 1e-3
elif abs_a > 1e-10 and abs_a <= 1e-8:
abs_a = abs_a * 1e4
elif abs_a > 1e-8 and abs_a <= 1e-6:
abs_a = abs_a * 1e2
elif self.is_bfloat16_op():
abs_a = 1 if abs_a < 1e-2 else abs_a
else:
abs_a = 1 if abs_a < 1e-3 else abs_a
if self.dtype == np.bool_:
diff_mat = np.abs(a ^ b) / abs_a
else:
diff_mat = np.abs(a - b) / abs_a
max_diff = np.max(diff_mat)
def err_msg():
offset = np.argmax(diff_mat > max_relative_error)
return (
"Operator %s error, %s variable %s (shape: %s, dtype: %s) max gradient diff %e over limit %e, "
"the first error element is %d, expected %e, but got %e."
) % (
self.op_type,
msg_prefix,
name,
str(a.shape),
self.dtype,
max_diff,
max_relative_error,
offset,
a.flatten()[offset],
b.flatten()[offset],
)
self.assertLessEqual(max_diff, max_relative_error, err_msg())
def _check_grad_helper(self):
self.infer_dtype_from_inputs_outputs(self.inputs, self.outputs)
self.__class__.op_type = self.op_type
self.__class__.exist_check_grad = True
if self.dtype == np.float64:
self.__class__.exist_fp64_check_grad = True
def check_grad(
self,
inputs_to_check,
output_names,
no_grad_set=None,
numeric_grad_delta=0.005,
in_place=False,
max_relative_error=0.005,
user_defined_grads=None,
user_defined_grad_outputs=None,
check_dygraph=True,
check_eager=False,
check_prim=False,
only_check_prim=False,
atol=1e-5,
):
# disable legacy dygraph check when check_eager is True
if check_eager:
check_dygraph = False
self._check_grad_helper()
places = self._get_places()
for place in places:
self.check_grad_with_place(
place,
inputs_to_check,
output_names,
no_grad_set,
numeric_grad_delta,
in_place,
max_relative_error,
user_defined_grads,
user_defined_grad_outputs,
check_dygraph,
check_eager=check_eager,
check_prim=check_prim,
only_check_prim=only_check_prim,
atol=atol,
)
def check_grad_with_place(
self,
place,
inputs_to_check,
output_names,
no_grad_set=None,
numeric_grad_delta=0.005,
in_place=False,
max_relative_error=0.005,
user_defined_grads=None,
user_defined_grad_outputs=None,
check_dygraph=True,
numeric_place=None,
check_eager=False,
check_prim=False,
only_check_prim=False,
atol=1e-5,
):
core._set_prim_all_enabled(False)
if check_prim:
prim_grad_checker = PrimGradChecker(
self,
place,
inputs_to_check,
output_names,
no_grad_set,
user_defined_grad_outputs,
)
prim_grad_checker.check()
# Support operators which not in the NO_FP64_CHECK_GRAD_OP_LIST list can be test prim with fp32
self.__class__.check_prim = True
self._check_grad_helper()
if only_check_prim:
return
# disable legacy dygraph check when check_eager is True
if check_eager:
check_dygraph = False
self.scope = core.Scope()
op_inputs = self.inputs if hasattr(self, "inputs") else {}
op_outputs = self.outputs if hasattr(self, "outputs") else {}
op_attrs = self.attrs if hasattr(self, "attrs") else {}
self._check_grad_helper()
if self.is_bfloat16_op():
if self.is_mkldnn_op():
check_dygraph = False
check_eager = False
atol = 1e-2 if atol < 1e-2 else atol
else:
atol = 1e-1 if atol < 1e-1 else atol
if self.is_float16_op():
atol = 1e-3 if atol < 1e-3 else atol
if (
self.dtype == np.float64
and self.op_type
not in op_threshold_white_list.NEED_FIX_FP64_CHECK_GRAD_THRESHOLD_OP_LIST
):
numeric_grad_delta = 1e-5
max_relative_error = 1e-7
cache_list = None
if hasattr(self, "cache_name_list"):
cache_list = self.cache_name_list
# oneDNN numeric gradient should use CPU kernel
use_onednn = False
if "use_mkldnn" in op_attrs and op_attrs["use_mkldnn"]:
op_attrs["use_mkldnn"] = False
use_onednn = True
self.op = create_op(
self.scope,
self.op_type,
op_inputs,
op_outputs,
op_attrs,
cache_list=cache_list,
)
if use_onednn:
op_attrs["use_mkldnn"] = True
if no_grad_set is None:
no_grad_set = set()
else:
if (
(self.op_type not in no_grad_set_white_list.NEED_TO_FIX_OP_LIST)
and (
self.op_type not in no_grad_set_white_list.NOT_CHECK_OP_LIST
)
and (not self.is_bfloat16_op())
):
raise AssertionError(
"no_grad_set must be None, op_type is "
+ self.op_type
+ " Op."
)
for input_to_check in inputs_to_check:
set_input(self.scope, self.op, self.inputs, place)
tensor_to_check = self.scope.find_var(input_to_check).get_tensor()
tensor_size = functools.reduce(
lambda a, b: a * b, tensor_to_check.shape(), 1
)
tensor_ndim = len(tensor_to_check.shape())
# for 0D Tensor, it's additional case for OP, so not raise error
if tensor_ndim > 0 and tensor_size < 100:
self.__class__.input_shape_is_large = False
if not type(output_names) is list:
output_names = [output_names]
if numeric_place is None:
numeric_place = place
if user_defined_grads is None and self.is_fp16_compared_with_fp32():
self.enable_cal_ref_output()
numeric_grads = self._get_gradient(
inputs_to_check,
place,
output_names,
no_grad_set,
user_defined_grad_outputs,
)
self.disable_cal_ref_output()
else:
numeric_grads = user_defined_grads or [
get_numeric_gradient(
numeric_place,
self.scope,
self.op,
self.inputs,
input_to_check,
output_names,
delta=numeric_grad_delta,
in_place=in_place,
)
for input_to_check in inputs_to_check
]
analytic_grads = self._get_gradient(
inputs_to_check,
place,
output_names,
no_grad_set,
user_defined_grad_outputs,
)
# comparison of bf16 results will happen as fp32
# loop over list of grads and convert bf16 to fp32
fp32_analytic_grads = []
for grad in analytic_grads:
if grad.dtype == np.uint16:
grad = convert_uint16_to_float(grad)
max_relative_error = (
0.01 if max_relative_error < 0.01 else max_relative_error
)
fp32_analytic_grads.append(grad)
analytic_grads = fp32_analytic_grads
fp32_numeric_grads = []
for grad in numeric_grads:
if grad.dtype == np.uint16:
grad = convert_uint16_to_float(grad)
max_relative_error = (
0.01 if max_relative_error < 0.01 else max_relative_error
)
fp32_numeric_grads.append(grad)
numeric_grads = fp32_numeric_grads
if self.is_float16_op():
max_relative_error = (
0.001 if max_relative_error < 0.001 else max_relative_error
)
self._assert_is_close(
numeric_grads,
analytic_grads,
inputs_to_check,
max_relative_error,
"Gradient Check On %s" % str(place),
atol=atol,
)
if check_dygraph:
# ensure switch into legacy dygraph
g_enable_legacy_dygraph()
dygraph_grad = self._get_dygraph_grad(
inputs_to_check,
place,
output_names,
user_defined_grad_outputs,
no_grad_set,
False,
)
fp32_grads = []
for grad in dygraph_grad:
if grad.dtype == np.uint16:
grad = convert_uint16_to_float(grad)
max_relative_error = (
0.03
if max_relative_error < 0.03
else max_relative_error
)
fp32_grads.append(grad)
dygraph_grad = fp32_grads
self._assert_is_close(
numeric_grads,
dygraph_grad,
inputs_to_check,
max_relative_error,
"Gradient Check On %s" % str(place),
atol=atol,
)
# ensure switch back eager dygraph
g_disable_legacy_dygraph()
if check_eager:
with fluid.dygraph.base.guard(place):
with _test_eager_guard():
eager_dygraph_grad = self._get_dygraph_grad(
inputs_to_check,
place,
output_names,
user_defined_grad_outputs,
no_grad_set,
check_eager,
)
fp32_grads = []
for grad in eager_dygraph_grad:
if grad.dtype == np.uint16:
grad = convert_uint16_to_float(grad)
max_relative_error = (
0.03
if max_relative_error < 0.03
else max_relative_error
)
fp32_grads.append(grad)
eager_dygraph_grad = fp32_grads
self._assert_is_close(
numeric_grads,
eager_dygraph_grad,
inputs_to_check,
max_relative_error,
"Gradient Check On %s" % str(place),
atol=atol,
)
def _find_var_in_dygraph(self, output_vars, name):
if name in output_vars:
return output_vars[name]
else:
for output_vars_index in output_vars:
for output_vars_selected in output_vars[output_vars_index]:
if output_vars_selected.name == name:
return output_vars_selected
def _get_dygraph_grad(
self,
inputs_to_check,
place,
output_names,
user_defined_grad_outputs=None,
no_grad_set=None,
check_eager=False,
):
with fluid.dygraph.base.guard(place=place):
block = fluid.default_main_program().global_block()
op_proto = OpProtoHolder.instance().get_op_proto(self.op_type)
# prepare input variable
inputs, inputs_grad_dict = self.append_input_output_for_dygraph(
op_proto, self.inputs, True, True, block
)
# prepare output variable
outputs = self.append_input_output_for_dygraph(
op_proto, self.outputs, False, False, block
)
# prepare attributes
attrs_outputs = {}
if hasattr(self, "attrs"):
for attrs_name in self.attrs:
if self.attrs[attrs_name] is not None:
attrs_outputs[attrs_name] = self.attrs[attrs_name]
if check_eager:
eager_outputs = self._calc_python_api_output(
place, inputs, outputs
)
# if outputs is None, kernel sig is empty or other error is happens.
if not check_eager or eager_outputs is None:
block.append_op(
type=self.op_type,
inputs=inputs,
outputs=outputs,
attrs=attrs_outputs if hasattr(self, "attrs") else None,
)
else:
outputs = eager_outputs
if self.dtype == np.uint16:
cast_inputs = self._find_var_in_dygraph(
outputs, output_names[0]
)
cast_outputs = block.create_var(
dtype="float32", shape=cast_inputs[0].shape
)
cast_op = block.append_op(
inputs={"X": cast_inputs},
outputs={"Out": cast_outputs},
type="cast",
attrs={
"in_dtype": core.VarDesc.VarType.BF16,
"out_dtype": core.VarDesc.VarType.FP32,
},
)
outputs = {output_names[0]: cast_outputs}
outputs_valid = {}
for output_name in output_names:
outputs_valid[output_name] = self._find_var_in_dygraph(
outputs, output_name
)
if user_defined_grad_outputs is None:
if len(outputs_valid) == 1:
loss = block.create_var(
dtype=self.dtype,
type=core.VarDesc.VarType.LOD_TENSOR,
persistable=False,
stop_gradient=False,
shape=[1],
)
for outputs_valid_key in outputs_valid:
block.append_op(
type="mean",
inputs={"X": outputs_valid[outputs_valid_key]},
outputs={"Out": [loss]},
attrs=None,
)
else:
avg_sum = []
for cur_loss in outputs_valid:
cur_avg_loss = block.create_var(
dtype=self.dtype,
type=core.VarDesc.VarType.LOD_TENSOR,
persistable=False,
stop_gradient=False,
)
block.append_op(
type="mean",
inputs={"X": outputs_valid[cur_loss]},
outputs={"Out": [cur_avg_loss]},
attrs=None,
)
avg_sum.append(cur_avg_loss)
loss_sum = block.create_var(
dtype=self.dtype,
type=core.VarDesc.VarType.LOD_TENSOR,
persistable=False,
stop_gradient=False,
shape=[1],
)
block.append_op(
type='sum',
inputs={"X": avg_sum},
outputs={"Out": loss_sum},
attrs=None,
)
loss = block.create_var(
dtype=self.dtype,
type=core.VarDesc.VarType.LOD_TENSOR,
persistable=False,
stop_gradient=False,
shape=[1],
)
block.append_op(
type='scale',
inputs={"X": loss_sum},
outputs={"Out": loss},
attrs={'scale': 1.0 / float(len(avg_sum))},
)
loss.backward()
fetch_list_grad = []
for inputs_to_check_name in inputs_to_check:
a = inputs_grad_dict[inputs_to_check_name].gradient()
fetch_list_grad.append(a)
return fetch_list_grad
else:
# user_defined_grad_outputs here are numpy arrays
if not isinstance(user_defined_grad_outputs, list):
user_defined_grad_outputs = [user_defined_grad_outputs]
grad_outputs = []
for grad_out_value in user_defined_grad_outputs:
grad_outputs.append(paddle.to_tensor(grad_out_value))
# delete the inputs which no need to calculate grad
for no_grad_val in no_grad_set:
del inputs[no_grad_val]
if in_dygraph_mode():
core.eager.run_backward(
paddle.utils.flatten(outputs),
grad_outputs,
False,
)
grad_inputs = []
for inputs_list in inputs.values():
for inp in inputs_list:
grad_inputs.append(inp.grad.numpy())
return grad_inputs
else:
grad_inputs = paddle.grad(
outputs=paddle.utils.flatten(outputs),
inputs=paddle.utils.flatten(inputs),
grad_outputs=grad_outputs,
)
return [grad.numpy() for grad in grad_inputs]
@staticmethod
def _numpy_to_lod_tensor(np_value, lod, place):
tensor = core.LoDTensor()
tensor.set(np_value, place)
if lod is not None:
tensor.set_recursive_sequence_lengths(lod)
return tensor
@staticmethod
def np_dtype_to_fluid_dtype(input):
return input
@staticmethod
def fluid_dtype_to_np_dtype(self, dtype):
return dtype
@staticmethod
def np_value_to_fluid_value(input):
return input
def _get_gradient(
self,
input_to_check,
place,
output_names,
no_grad_set,
user_defined_grad_outputs=None,
parallel=False,
):
with paddle.fluid.framework._static_guard():
prog = Program()
scope = core.Scope()
block = prog.global_block()
self._append_ops(block)
inputs = self._get_inputs(block)
outputs = self._get_outputs(block)
feed_dict = self.feed_var(inputs, place)
if user_defined_grad_outputs is None:
if self.dtype == np.uint16:
cast_inputs = list(map(block.var, output_names))
cast_outputs = block.create_var(
dtype="float32", shape=cast_inputs[0].shape
)
cast_op = block.append_op(
inputs={"X": cast_inputs},
outputs={"Out": cast_outputs},
type="cast",
attrs={
"in_dtype": core.VarDesc.VarType.BF16,
"out_dtype": core.VarDesc.VarType.FP32,
},
)
cast_op.desc.infer_var_type(block.desc)
cast_op.desc.infer_shape(block.desc)
output_names = [cast_outputs.name]
loss = append_loss_ops(block, output_names)
param_grad_list = append_backward(
loss=loss,
parameter_list=input_to_check,
no_grad_set=no_grad_set,
)
fetch_list = [g for p, g in param_grad_list]
else:
assert (
parallel is False
), "unsupported parallel mode when giving custom grad outputs."
# user_defined_grad_outputs here are numpy arrays
if not isinstance(user_defined_grad_outputs, list):
user_defined_grad_outputs = [user_defined_grad_outputs]
grad_outputs = []
for grad_out_value in user_defined_grad_outputs:
# `presistable` is used to avoid executor create new var in local scope
var = block.create_var(
shape=grad_out_value.shape,
dtype=grad_out_value.dtype,
persistable=True,
)
true_var = scope.var(var.name)
tensor = true_var.get_tensor()
tensor.set(grad_out_value, place)
grad_outputs.append(var)
targets = [
outputs[name] for name in outputs if name in output_names
]
inputs = [
inputs[name] for name in input_to_check if name in inputs
]
grad_inputs = paddle.static.gradients(
targets, inputs, grad_outputs, no_grad_set
)
fetch_list = grad_inputs
if parallel:
use_cuda = False
if isinstance(place, fluid.CUDAPlace):
use_cuda = True
compiled_prog = fluid.CompiledProgram(prog)
prog = compiled_prog
executor = fluid.Executor(place)
res = list(
map(
np.array,
executor.run(
prog,
feed_dict,
fetch_list,
scope=scope,
return_numpy=False,
),
)
)
return res
class OpTestTool:
@classmethod
def skip_if(cls, condition: object, reason: str):
return unittest.skipIf(condition, reason)
@classmethod
def skip_if_not_cpu_bf16(cls):
return OpTestTool.skip_if(
not (
isinstance(_current_expected_place(), core.CPUPlace)
and core.supports_bfloat16()
),
"Place does not support BF16 evaluation",
)
@classmethod
def skip_if_not_cpu(cls):
return OpTestTool.skip_if(
not isinstance(_current_expected_place(), core.CPUPlace),
"OneDNN supports only CPU for now",
)
...@@ -19,7 +19,7 @@ import numpy as np ...@@ -19,7 +19,7 @@ import numpy as np
import paddle import paddle
from paddle import fluid from paddle import fluid
from paddle.fluid.dygraph import to_variable from paddle.fluid.dygraph import to_variable
from paddle.fluid.framework import EagerParamBase, ParamBase, in_dygraph_mode from paddle.fluid.framework import EagerParamBase
class L1(paddle.nn.Layer): class L1(paddle.nn.Layer):
...@@ -184,14 +184,9 @@ class TestBuffer(unittest.TestCase): ...@@ -184,14 +184,9 @@ class TestBuffer(unittest.TestCase):
with self.assertRaisesRegex( with self.assertRaisesRegex(
TypeError, "buffer should be a Paddle.Tensor" TypeError, "buffer should be a Paddle.Tensor"
): ):
if in_dygraph_mode(): net.register_buffer(
net.register_buffer( "buffer_name", EagerParamBase([2, 2], 'float32')
"buffer_name", EagerParamBase([2, 2], 'float32') )
)
else:
net.register_buffer(
"buffer_name", ParamBase([2, 2], 'float32')
)
with self.assertRaisesRegex( with self.assertRaisesRegex(
KeyError, "name of buffer can not contain" KeyError, "name of buffer can not contain"
...@@ -208,10 +203,7 @@ class TestBuffer(unittest.TestCase): ...@@ -208,10 +203,7 @@ class TestBuffer(unittest.TestCase):
net.register_buffer("attr_name", var) net.register_buffer("attr_name", var)
del net.attr_name del net.attr_name
if in_dygraph_mode(): net.attr_name = EagerParamBase([2, 2], 'float32')
net.attr_name = EagerParamBase([2, 2], 'float32')
else:
net.attr_name = ParamBase([2, 2], 'float32')
with self.assertRaisesRegex(KeyError, "already exists"): with self.assertRaisesRegex(KeyError, "already exists"):
net.register_buffer("attr_name", var) net.register_buffer("attr_name", var)
...@@ -278,11 +270,8 @@ class TestBuffer(unittest.TestCase): ...@@ -278,11 +270,8 @@ class TestBuffer(unittest.TestCase):
self.assertEqual(len(net.buffers()), 1) self.assertEqual(len(net.buffers()), 1)
self.assertEqual(len(net.state_dict()), 0) self.assertEqual(len(net.state_dict()), 0)
# Re-assign a ParamBase will remove the buffer. # Re-assign a EagerParamBase will remove the buffer.
if in_dygraph_mode(): net.buffer_name = EagerParamBase([2, 2], 'float32')
net.buffer_name = EagerParamBase([2, 2], 'float32')
else:
net.buffer_name = ParamBase([2, 2], 'float32')
self.assertEqual(len(net.buffers()), 0) self.assertEqual(len(net.buffers()), 0)
self.assertEqual(len(net.state_dict()), 1) self.assertEqual(len(net.state_dict()), 1)
...@@ -403,12 +392,9 @@ class TestLayerTo(unittest.TestCase): ...@@ -403,12 +392,9 @@ class TestLayerTo(unittest.TestCase):
paddle.fluid.core.VarDesc.VarType.FP64, paddle.fluid.core.VarDesc.VarType.FP64,
) )
for p in self.linear.parameters(): for p in self.linear.parameters():
if in_dygraph_mode(): self.assertTrue(
self.assertTrue( isinstance(p, paddle.fluid.framework.EagerParamBase)
isinstance(p, paddle.fluid.framework.EagerParamBase) )
)
else:
self.assertTrue(isinstance(p, paddle.fluid.framework.ParamBase))
if paddle.fluid.is_compiled_with_cuda(): if paddle.fluid.is_compiled_with_cuda():
self.linear.to(device=paddle.CUDAPlace(0)) self.linear.to(device=paddle.CUDAPlace(0))
...@@ -435,14 +421,9 @@ class TestLayerTo(unittest.TestCase): ...@@ -435,14 +421,9 @@ class TestLayerTo(unittest.TestCase):
self.linear.weight._grad_ivar().place.gpu_device_id(), 0 self.linear.weight._grad_ivar().place.gpu_device_id(), 0
) )
for p in self.linear.parameters(): for p in self.linear.parameters():
if in_dygraph_mode(): self.assertTrue(
self.assertTrue( isinstance(p, paddle.fluid.framework.EagerParamBase)
isinstance(p, paddle.fluid.framework.EagerParamBase) )
)
else:
self.assertTrue(
isinstance(p, paddle.fluid.framework.ParamBase)
)
self.linear.to(device=paddle.CPUPlace()) self.linear.to(device=paddle.CPUPlace())
self.assertTrue(self.linear.weight.place.is_cpu_place()) self.assertTrue(self.linear.weight.place.is_cpu_place())
...@@ -489,12 +470,9 @@ class TestLayerTo(unittest.TestCase): ...@@ -489,12 +470,9 @@ class TestLayerTo(unittest.TestCase):
paddle.fluid.core.VarDesc.VarType.FP64, paddle.fluid.core.VarDesc.VarType.FP64,
) )
for p in self.linear.parameters(): for p in self.linear.parameters():
if in_dygraph_mode(): self.assertTrue(
self.assertTrue( isinstance(p, paddle.fluid.framework.EagerParamBase)
isinstance(p, paddle.fluid.framework.EagerParamBase) )
)
else:
self.assertTrue(isinstance(p, paddle.fluid.framework.ParamBase))
def func_test_to_api_numpy_dtype(self): def func_test_to_api_numpy_dtype(self):
self.linear.to(dtype=np.float64) self.linear.to(dtype=np.float64)
...@@ -527,12 +505,9 @@ class TestLayerTo(unittest.TestCase): ...@@ -527,12 +505,9 @@ class TestLayerTo(unittest.TestCase):
paddle.fluid.core.VarDesc.VarType.FP64, paddle.fluid.core.VarDesc.VarType.FP64,
) )
for p in self.linear.parameters(): for p in self.linear.parameters():
if in_dygraph_mode(): self.assertTrue(
self.assertTrue( isinstance(p, paddle.fluid.framework.EagerParamBase)
isinstance(p, paddle.fluid.framework.EagerParamBase) )
)
else:
self.assertTrue(isinstance(p, paddle.fluid.framework.ParamBase))
def func_test_to_api_none_buffer(self): def func_test_to_api_none_buffer(self):
model = paddle.nn.Linear(2, 4) model = paddle.nn.Linear(2, 4)
......
...@@ -30,7 +30,7 @@ from test_conv2d_op import ( ...@@ -30,7 +30,7 @@ from test_conv2d_op import (
) )
from paddle.fluid import core from paddle.fluid import core
from paddle.fluid.tests.unittests.op_test import get_numeric_gradient from paddle.fluid.tests.unittests.eager_op_test import get_numeric_gradient
from paddle.fluid.tests.unittests.testsuite import create_op from paddle.fluid.tests.unittests.testsuite import create_op
# ----------------TestDepthwiseConv ----- # ----------------TestDepthwiseConv -----
...@@ -416,14 +416,14 @@ def create_test_fp16_class(parent, grad_check=True): ...@@ -416,14 +416,14 @@ def create_test_fp16_class(parent, grad_check=True):
place = core.CUDAPlace(0) place = core.CUDAPlace(0)
if core.is_float16_supported(place) and grad_check: if core.is_float16_supported(place) and grad_check:
self.check_grad_with_place( self.check_grad_with_place(
place, ['Input'], 'Output', no_grad_set=set(['Filter']) place, ['Input'], 'Output', no_grad_set={'Filter'}
) )
def test_check_grad_no_input(self): def test_check_grad_no_input(self):
place = core.CUDAPlace(0) place = core.CUDAPlace(0)
if core.is_float16_supported(place) and grad_check: if core.is_float16_supported(place) and grad_check:
self.check_grad_with_place( self.check_grad_with_place(
place, ['Filter'], 'Output', no_grad_set=set(['Input']) place, ['Filter'], 'Output', no_grad_set={'Input'}
) )
cls_name = "{0}_{1}".format(parent.__name__, "FP16OP") cls_name = "{0}_{1}".format(parent.__name__, "FP16OP")
...@@ -464,7 +464,7 @@ def create_test_bf16_class(parent, atol=1e-2): ...@@ -464,7 +464,7 @@ def create_test_bf16_class(parent, atol=1e-2):
place, place,
['Input'], ['Input'],
'Output', 'Output',
no_grad_set=set(['Filter']), no_grad_set={'Filter'},
user_defined_grads=[numeric_grads], user_defined_grads=[numeric_grads],
) )
...@@ -475,7 +475,7 @@ def create_test_bf16_class(parent, atol=1e-2): ...@@ -475,7 +475,7 @@ def create_test_bf16_class(parent, atol=1e-2):
place, place,
['Filter'], ['Filter'],
'Output', 'Output',
no_grad_set=set(['Input']), no_grad_set={'Input'},
user_defined_grads=[numeric_grads], user_defined_grads=[numeric_grads],
) )
...@@ -503,14 +503,14 @@ def create_test_channel_last_fp16_class(parent, grad_check=True): ...@@ -503,14 +503,14 @@ def create_test_channel_last_fp16_class(parent, grad_check=True):
place = core.CUDAPlace(0) place = core.CUDAPlace(0)
if core.is_float16_supported(place) and grad_check: if core.is_float16_supported(place) and grad_check:
self.check_grad_with_place( self.check_grad_with_place(
place, ['Input'], 'Output', no_grad_set=set(['Filter']) place, ['Input'], 'Output', no_grad_set={'Filter'}
) )
def test_check_grad_no_input(self): def test_check_grad_no_input(self):
place = core.CUDAPlace(0) place = core.CUDAPlace(0)
if core.is_float16_supported(place) and grad_check: if core.is_float16_supported(place) and grad_check:
self.check_grad_with_place( self.check_grad_with_place(
place, ['Filter'], 'Output', no_grad_set=set(['Input']) place, ['Filter'], 'Output', no_grad_set={'Input'}
) )
def init_data_format(self): def init_data_format(self):
......
...@@ -44,7 +44,7 @@ def _append_backward_desc(main_program, outs): ...@@ -44,7 +44,7 @@ def _append_backward_desc(main_program, outs):
# def _set_grad_type(params, train_program): # def _set_grad_type(params, train_program):
# # NOTE: if user set sparse gradient mode, the param's gradient # # NOTE: if user set sparse gradient mode, the param's gradient
# # will be SelectedRows, not LoDTensor. But tracer will just # # will be SelectedRows, not LoDTensor. But tracer will just
# # set param grad VarBase by forward VarBase(LoDTensor) # # set param grad Tensor by forward Tensor(LoDTensor)
# # If we don't change grad_var type here, RunProgramOp need # # If we don't change grad_var type here, RunProgramOp need
# # transform SelectedRows to LoDTensor forcibly, it may not # # transform SelectedRows to LoDTensor forcibly, it may not
# # be user wanted result. # # be user wanted result.
......
...@@ -600,7 +600,7 @@ class TestSimpleUndiagonal2(unittest.TestCase): ...@@ -600,7 +600,7 @@ class TestSimpleUndiagonal2(unittest.TestCase):
class TestSimpleComplexGrad(unittest.TestCase): class TestSimpleComplexGrad(unittest.TestCase):
""" """
EinsumOp support complex grad. but op_test don't support numeric grad for complex dtype. EinsumOp support complex grad. but eager_op_test don't support numeric grad for complex dtype.
""" """
def test_shape(self): def test_shape(self):
......
...@@ -321,7 +321,7 @@ class TestDygraphPtbRnn(unittest.TestCase): ...@@ -321,7 +321,7 @@ class TestDygraphPtbRnn(unittest.TestCase):
self.opti_dict = adam.state_dict() self.opti_dict = adam.state_dict()
self.base_opti = {} self.base_opti = {}
for k, v in self.opti_dict.items(): for k, v in self.opti_dict.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
self.base_opti[v.name] = v.numpy() self.base_opti[v.name] = v.numpy()
self.assertTrue(np.sum(np.abs(v.numpy())) != 0) self.assertTrue(np.sum(np.abs(v.numpy())) != 0)
else: else:
...@@ -423,7 +423,7 @@ class TestDygraphPtbRnn(unittest.TestCase): ...@@ -423,7 +423,7 @@ class TestDygraphPtbRnn(unittest.TestCase):
opti_dict = adam.state_dict() opti_dict = adam.state_dict()
# set to zero # set to zero
for k, v in opti_dict.items(): for k, v in opti_dict.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
np_t = v.numpy() np_t = v.numpy()
var = v.value().get_tensor() var = v.value().get_tensor()
var.set(np.zeros_like(np_t), place) var.set(np.zeros_like(np_t), place)
...@@ -440,7 +440,7 @@ class TestDygraphPtbRnn(unittest.TestCase): ...@@ -440,7 +440,7 @@ class TestDygraphPtbRnn(unittest.TestCase):
opti_dict = adam.state_dict() opti_dict = adam.state_dict()
for k, v in opti_dict.items(): for k, v in opti_dict.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
np.testing.assert_array_equal( np.testing.assert_array_equal(
v.numpy(), self.base_opti[v.name] v.numpy(), self.base_opti[v.name]
) )
...@@ -545,7 +545,7 @@ class TestDygraphPtbRnn(unittest.TestCase): ...@@ -545,7 +545,7 @@ class TestDygraphPtbRnn(unittest.TestCase):
opti_dict = adam.state_dict() opti_dict = adam.state_dict()
# set to zero # set to zero
for k, v in opti_dict.items(): for k, v in opti_dict.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
np_t = v.numpy() np_t = v.numpy()
var = v.value().get_tensor() var = v.value().get_tensor()
var.set(np.zeros_like(np_t), place) var.set(np.zeros_like(np_t), place)
...@@ -558,7 +558,7 @@ class TestDygraphPtbRnn(unittest.TestCase): ...@@ -558,7 +558,7 @@ class TestDygraphPtbRnn(unittest.TestCase):
adam.set_state_dict(self.opti_dict) adam.set_state_dict(self.opti_dict)
opti_dict = adam.state_dict() opti_dict = adam.state_dict()
for k, v in opti_dict.items(): for k, v in opti_dict.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
np.testing.assert_array_equal( np.testing.assert_array_equal(
v.numpy(), self.base_opti[v.name] v.numpy(), self.base_opti[v.name]
) )
...@@ -664,7 +664,7 @@ class TestDygraphPtbRnn(unittest.TestCase): ...@@ -664,7 +664,7 @@ class TestDygraphPtbRnn(unittest.TestCase):
np_opti_dict = {} np_opti_dict = {}
# set to zero # set to zero
for k, v in opti_dict.items(): for k, v in opti_dict.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
np_t = v.numpy() np_t = v.numpy()
np_opti_dict[v.name] = np_t np_opti_dict[v.name] = np_t
var = v.value().get_tensor() var = v.value().get_tensor()
...@@ -680,7 +680,7 @@ class TestDygraphPtbRnn(unittest.TestCase): ...@@ -680,7 +680,7 @@ class TestDygraphPtbRnn(unittest.TestCase):
opti_dict = adam.state_dict() opti_dict = adam.state_dict()
for k, v in opti_dict.items(): for k, v in opti_dict.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
np.testing.assert_array_equal( np.testing.assert_array_equal(
v.numpy(), self.base_opti[v.name] v.numpy(), self.base_opti[v.name]
) )
...@@ -953,7 +953,7 @@ class TestDygraphPtbRnn(unittest.TestCase): ...@@ -953,7 +953,7 @@ class TestDygraphPtbRnn(unittest.TestCase):
np_state_dict = {} np_state_dict = {}
for k, v in self.opti_dict.items(): for k, v in self.opti_dict.items():
if isinstance(v, (core.VarBase, core.eager.Tensor)): if isinstance(v, core.eager.Tensor):
np_opti_dict[v.name] = v.numpy() np_opti_dict[v.name] = v.numpy()
else: else:
np_opti_dict[k] = v np_opti_dict[k] = v
......
...@@ -82,12 +82,8 @@ class TestTensorDataset(unittest.TestCase): ...@@ -82,12 +82,8 @@ class TestTensorDataset(unittest.TestCase):
assert len(label) == 1 assert len(label) == 1
assert input.shape == [1, 3, 4] assert input.shape == [1, 3, 4]
assert label.shape == [1, 1] assert label.shape == [1, 1]
assert isinstance( assert isinstance(input, fluid.core.eager.Tensor)
input, (fluid.core.VarBase, fluid.core.eager.Tensor) assert isinstance(label, fluid.core.eager.Tensor)
)
assert isinstance(
label, (fluid.core.VarBase, fluid.core.eager.Tensor)
)
assert np.allclose(input.numpy(), input_np[i]) assert np.allclose(input.numpy(), input_np[i])
assert np.allclose(label.numpy(), label_np[i]) assert np.allclose(label.numpy(), label_np[i])
...@@ -184,12 +180,8 @@ class TestSubsetDataset(unittest.TestCase): ...@@ -184,12 +180,8 @@ class TestSubsetDataset(unittest.TestCase):
assert len(label) == 1 assert len(label) == 1
assert input.shape == [1, 3, 4] assert input.shape == [1, 3, 4]
assert label.shape == [1, 1] assert label.shape == [1, 1]
assert isinstance( assert isinstance(input, fluid.core.eager.Tensor)
input, (fluid.core.VarBase, fluid.core.eager.Tensor) assert isinstance(label, fluid.core.eager.Tensor)
)
assert isinstance(
label, (fluid.core.VarBase, fluid.core.eager.Tensor)
)
elements_list = [] elements_list = []
for _, (input, label) in enumerate(dataloader()): for _, (input, label) in enumerate(dataloader()):
...@@ -285,12 +277,8 @@ class TestNumpyMixTensorDataset(TestTensorDataset): ...@@ -285,12 +277,8 @@ class TestNumpyMixTensorDataset(TestTensorDataset):
assert len(label) == 1 assert len(label) == 1
assert input.shape == [1, IMAGE_SIZE] assert input.shape == [1, IMAGE_SIZE]
assert label.shape == [1, 1] assert label.shape == [1, 1]
assert isinstance( assert isinstance(input, fluid.core.eager.Tensor)
input, (fluid.core.VarBase, fluid.core.eager.Tensor) assert isinstance(label, fluid.core.eager.Tensor)
)
assert isinstance(
label, (fluid.core.VarBase, fluid.core.eager.Tensor)
)
class ComplextDataset(Dataset): class ComplextDataset(Dataset):
...@@ -385,9 +373,7 @@ class TestSingleFieldDataset(unittest.TestCase): ...@@ -385,9 +373,7 @@ class TestSingleFieldDataset(unittest.TestCase):
) )
for i, data in enumerate(dataloader()): for i, data in enumerate(dataloader()):
assert isinstance( assert isinstance(data, fluid.core.eager.Tensor)
data, (fluid.core.VarBase, fluid.core.eager.Tensor)
)
assert data.shape == [2, 2, 3] assert data.shape == [2, 2, 3]
def test_main(self): def test_main(self):
......
...@@ -20,7 +20,7 @@ from eager_op_test import OpTest ...@@ -20,7 +20,7 @@ from eager_op_test import OpTest
import paddle import paddle
from paddle import fluid from paddle import fluid
from paddle.fluid import Program, program_guard from paddle.fluid import Program, program_guard
from paddle.fluid.tests.unittests.op_test import convert_float_to_uint16 from paddle.fluid.tests.unittests.eager_op_test import convert_float_to_uint16
def call_nonzero(x): def call_nonzero(x):
......
...@@ -360,7 +360,7 @@ class TestSaveLoadAny(unittest.TestCase): ...@@ -360,7 +360,7 @@ class TestSaveLoadAny(unittest.TestCase):
self.assertTrue( self.assertTrue(
isinstance( isinstance(
t_dygraph, t_dygraph,
(paddle.fluid.core.VarBase, paddle.fluid.core.eager.Tensor), paddle.fluid.core.eager.Tensor,
) )
) )
np.testing.assert_array_equal(tensor.numpy(), np_dygraph) np.testing.assert_array_equal(tensor.numpy(), np_dygraph)
...@@ -788,14 +788,14 @@ class TestSaveLoadAny(unittest.TestCase): ...@@ -788,14 +788,14 @@ class TestSaveLoadAny(unittest.TestCase):
self.assertTrue( self.assertTrue(
isinstance( isinstance(
load_tensor3[0], load_tensor3[0],
(fluid.core.VarBase, fluid.core.eager.Tensor), fluid.core.eager.Tensor,
) )
) )
np.testing.assert_array_equal(load_tensor3[0].numpy(), obj3[0]) np.testing.assert_array_equal(load_tensor3[0].numpy(), obj3[0])
self.assertTrue( self.assertTrue(
isinstance( isinstance(
load_tensor3[1], load_tensor3[1],
(fluid.core.VarBase, fluid.core.eager.Tensor), fluid.core.eager.Tensor,
) )
) )
np.testing.assert_array_equal(load_tensor3[1].numpy(), obj3[1]) np.testing.assert_array_equal(load_tensor3[1].numpy(), obj3[1])
...@@ -804,7 +804,7 @@ class TestSaveLoadAny(unittest.TestCase): ...@@ -804,7 +804,7 @@ class TestSaveLoadAny(unittest.TestCase):
self.assertTrue( self.assertTrue(
isinstance( isinstance(
load_tensor3[2]["state_dict"][k], load_tensor3[2]["state_dict"][k],
(fluid.core.VarBase, fluid.core.eager.Tensor), fluid.core.eager.Tensor,
) )
) )
np.testing.assert_array_equal( np.testing.assert_array_equal(
...@@ -815,7 +815,7 @@ class TestSaveLoadAny(unittest.TestCase): ...@@ -815,7 +815,7 @@ class TestSaveLoadAny(unittest.TestCase):
self.assertTrue( self.assertTrue(
isinstance( isinstance(
load_tensor3[2]["opt"][k], load_tensor3[2]["opt"][k],
(fluid.core.VarBase, fluid.core.eager.Tensor), fluid.core.eager.Tensor,
) )
) )
np.testing.assert_array_equal( np.testing.assert_array_equal(
...@@ -825,7 +825,7 @@ class TestSaveLoadAny(unittest.TestCase): ...@@ -825,7 +825,7 @@ class TestSaveLoadAny(unittest.TestCase):
self.assertTrue( self.assertTrue(
isinstance( isinstance(
load_tensor4[0], load_tensor4[0],
(fluid.core.VarBase, fluid.core.eager.Tensor), fluid.core.eager.Tensor,
) )
) )
np.testing.assert_array_equal(load_tensor4[0].numpy(), obj4[0]) np.testing.assert_array_equal(load_tensor4[0].numpy(), obj4[0])
......
...@@ -21,7 +21,7 @@ import paddle ...@@ -21,7 +21,7 @@ import paddle
from paddle.fluid import core from paddle.fluid import core
from paddle.fluid.dygraph import guard from paddle.fluid.dygraph import guard
from paddle.fluid.executor import Executor from paddle.fluid.executor import Executor
from paddle.fluid.framework import ParamBase, Variable, default_main_program from paddle.fluid.framework import Variable, default_main_program
paddle.enable_static() paddle.enable_static()
main_program = default_main_program() main_program = default_main_program()
...@@ -73,9 +73,6 @@ class ParameterChecks(unittest.TestCase): ...@@ -73,9 +73,6 @@ class ParameterChecks(unittest.TestCase):
pram_copy2 = copy.deepcopy(param, memo) pram_copy2 = copy.deepcopy(param, memo)
self.assertEqual(id(param_copy), id(pram_copy2)) self.assertEqual(id(param_copy), id(pram_copy2))
zero_dim_param = ParamBase(shape=[], dtype='float32')
self.assertEqual(zero_dim_param.shape, [])
def func_exception(self): def func_exception(self):
b = main_program.global_block() b = main_program.global_block()
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
......
...@@ -20,11 +20,6 @@ import paddle ...@@ -20,11 +20,6 @@ import paddle
from paddle.autograd.py_layer import PyLayer from paddle.autograd.py_layer import PyLayer
class FakeTensor(paddle.fluid.core.VarBase):
def __init__(self):
pass
class TestPyLayer(unittest.TestCase): class TestPyLayer(unittest.TestCase):
def test_simple_pylayer_multiple_output(self): def test_simple_pylayer_multiple_output(self):
class tanh(PyLayer): class tanh(PyLayer):
......
...@@ -175,14 +175,9 @@ class RunProgramOpTest(unittest.TestCase): ...@@ -175,14 +175,9 @@ class RunProgramOpTest(unittest.TestCase):
def prepare_dygraph_input(self, place, return_param_list=False): def prepare_dygraph_input(self, place, return_param_list=False):
def create_var_base(is_input, name, np_value, stop_gradient): def create_var_base(is_input, name, np_value, stop_gradient):
if global_var._in_eager_mode_: var = core.eager.Tensor(
var = core.eager.Tensor( value=np_value, name=name, place=place, zero_copy=True
value=np_value, name=name, place=place, zero_copy=True )
)
else:
var = core.VarBase(
value=np_value, name=name, place=place, zero_copy=True
)
var.stop_gradient = stop_gradient var.stop_gradient = stop_gradient
return var return var
......
...@@ -17,7 +17,6 @@ import unittest ...@@ -17,7 +17,6 @@ import unittest
import numpy as np import numpy as np
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
class TestTrapezoidAPI(unittest.TestCase): class TestTrapezoidAPI(unittest.TestCase):
...@@ -61,9 +60,6 @@ class TestTrapezoidAPI(unittest.TestCase): ...@@ -61,9 +60,6 @@ class TestTrapezoidAPI(unittest.TestCase):
np.testing.assert_allclose(out, self.output, rtol=1e-05) np.testing.assert_allclose(out, self.output, rtol=1e-05)
def test_dygraph(self): def test_dygraph(self):
with _test_eager_guard():
self.setUp()
self.func_dygraph()
self.setUp() self.setUp()
self.func_dygraph() self.func_dygraph()
...@@ -267,8 +263,6 @@ class Testfp16Trapezoid(TestTrapezoidAPI): ...@@ -267,8 +263,6 @@ class Testfp16Trapezoid(TestTrapezoidAPI):
out = self.paddle_api(y=y, x=x) out = self.paddle_api(y=y, x=x)
def test_fp16_dygraph(self): def test_fp16_dygraph(self):
with _test_eager_guard():
self.func_dygraph()
self.func_dygraph() self.func_dygraph()
......
...@@ -1018,9 +1018,7 @@ class TestVarBase(unittest.TestCase): ...@@ -1018,9 +1018,7 @@ class TestVarBase(unittest.TestCase):
def test_var_base_to_np(self): def test_var_base_to_np(self):
with fluid.dygraph.guard(): with fluid.dygraph.guard():
var = fluid.dygraph.to_variable(self.array) var = fluid.dygraph.to_variable(self.array)
np.testing.assert_array_equal( np.testing.assert_array_equal(var.numpy(), var.numpy(False))
var.numpy(), fluid.framework._var_base_to_np(var)
)
def test_var_base_as_np(self): def test_var_base_as_np(self):
with fluid.dygraph.guard(): with fluid.dygraph.guard():
...@@ -1051,7 +1049,7 @@ class TestVarBase(unittest.TestCase): ...@@ -1051,7 +1049,7 @@ class TestVarBase(unittest.TestCase):
def test_to_static_var(self): def test_to_static_var(self):
with fluid.dygraph.guard(): with fluid.dygraph.guard():
# Convert VarBase into Variable or Parameter # Convert Tensor into Variable or Parameter
var_base = fluid.dygraph.to_variable(self.array, name="var_base_1") var_base = fluid.dygraph.to_variable(self.array, name="var_base_1")
static_var = var_base._to_static_var() static_var = var_base._to_static_var()
self._assert_to_static(var_base, static_var) self._assert_to_static(var_base, static_var)
...@@ -1060,7 +1058,7 @@ class TestVarBase(unittest.TestCase): ...@@ -1060,7 +1058,7 @@ class TestVarBase(unittest.TestCase):
static_param = var_base._to_static_var(to_parameter=True) static_param = var_base._to_static_var(to_parameter=True)
self._assert_to_static(var_base, static_param, True) self._assert_to_static(var_base, static_param, True)
# Convert ParamBase into Parameter # Convert EagerParamBase into Parameter
fc = paddle.nn.Linear( fc = paddle.nn.Linear(
10, 10,
20, 20,
...@@ -1078,7 +1076,7 @@ class TestVarBase(unittest.TestCase): ...@@ -1078,7 +1076,7 @@ class TestVarBase(unittest.TestCase):
if is_param: if is_param:
self.assertTrue(isinstance(static_var, fluid.framework.Parameter)) self.assertTrue(isinstance(static_var, fluid.framework.Parameter))
self.assertTrue(static_var.persistable, True) self.assertTrue(static_var.persistable, True)
if isinstance(var_base, fluid.framework.ParamBase): if isinstance(var_base, fluid.framework.EagerParamBase):
for attr in ['trainable', 'is_distributed', 'do_model_average']: for attr in ['trainable', 'is_distributed', 'do_model_average']:
self.assertEqual( self.assertEqual(
getattr(var_base, attr), getattr(static_var, attr) getattr(var_base, attr), getattr(static_var, attr)
......
...@@ -27,7 +27,6 @@ from xpu.get_test_cover_info import ( ...@@ -27,7 +27,6 @@ from xpu.get_test_cover_info import (
import paddle import paddle
from paddle import fluid, tensor from paddle import fluid, tensor
from paddle.fluid import Program, program_guard from paddle.fluid import Program, program_guard
from paddle.fluid.framework import _test_eager_guard
paddle.enable_static() paddle.enable_static()
...@@ -74,8 +73,7 @@ class XPUTestUnbindOP(XPUOpTestWrapper): ...@@ -74,8 +73,7 @@ class XPUTestUnbindOP(XPUOpTestWrapper):
np.testing.assert_array_equal(x.grad.numpy(), np_grad) np.testing.assert_array_equal(x.grad.numpy(), np_grad)
def test_unbind_dygraph_final_state(self): def test_unbind_dygraph_final_state(self):
with _test_eager_guard(): self.test_unbind_dygraph()
self.test_unbind_dygraph()
class TestLayersUnbind(unittest.TestCase): class TestLayersUnbind(unittest.TestCase):
def test_layers_unbind(self): def test_layers_unbind(self):
......
...@@ -27,7 +27,6 @@ from ..fluid.core import CUDAPinnedPlace # noqa: F401 ...@@ -27,7 +27,6 @@ from ..fluid.core import CUDAPinnedPlace # noqa: F401
from ..fluid.core import NPUPlace # noqa: F401 from ..fluid.core import NPUPlace # noqa: F401
from ..fluid.core import MLUPlace # noqa: F401 from ..fluid.core import MLUPlace # noqa: F401
from ..fluid.core import CustomPlace # noqa: F401 from ..fluid.core import CustomPlace # noqa: F401
from ..fluid.core import VarBase # noqa: F401
from ..fluid import core # noqa: F401 from ..fluid import core # noqa: F401
from ..fluid.dygraph import base, to_variable from ..fluid.dygraph import base, to_variable
...@@ -51,7 +50,7 @@ from ..fluid.dygraph import monkey_patch_math_varbase ...@@ -51,7 +50,7 @@ from ..fluid.dygraph import monkey_patch_math_varbase
from ..fluid.framework import disable_signal_handler # noqa: F401 from ..fluid.framework import disable_signal_handler # noqa: F401
from ..fluid.framework import get_flags # noqa: F401 from ..fluid.framework import get_flags # noqa: F401
from ..fluid.framework import set_flags # noqa: F401 from ..fluid.framework import set_flags # noqa: F401
from ..fluid.framework import Parameter, ParamBase from ..fluid.framework import Parameter
from ..fluid.dygraph.base import enable_dygraph as disable_static # noqa: F401 from ..fluid.dygraph.base import enable_dygraph as disable_static # noqa: F401
from ..fluid.dygraph.base import disable_dygraph as enable_static # noqa: F401 from ..fluid.dygraph.base import disable_dygraph as enable_static # noqa: F401
from ..fluid.framework import _non_static_mode as in_dynamic_mode # noqa: F401 from ..fluid.framework import _non_static_mode as in_dynamic_mode # noqa: F401
......
...@@ -29,7 +29,6 @@ from paddle import fluid ...@@ -29,7 +29,6 @@ from paddle import fluid
from paddle.fluid import core from paddle.fluid import core
from paddle.fluid.framework import ( from paddle.fluid.framework import (
EagerParamBase, EagerParamBase,
ParamBase,
Program, Program,
Variable, Variable,
_current_expected_place, _current_expected_place,
...@@ -55,7 +54,7 @@ def _build_saved_state_dict(state_dict): ...@@ -55,7 +54,7 @@ def _build_saved_state_dict(state_dict):
save_dict = {} save_dict = {}
name_table = {} name_table = {}
for key, value in state_dict.items(): for key, value in state_dict.items():
if isinstance(value, (Variable, core.VarBase, core.eager.Tensor)): if isinstance(value, (Variable, core.eager.Tensor)):
if value.type == core.VarDesc.VarType.VOCAB: if value.type == core.VarDesc.VarType.VOCAB:
save_dict[key] = value.value().get_map_tensor() save_dict[key] = value.value().get_map_tensor()
else: else:
...@@ -118,8 +117,8 @@ def _load_state_dict_from_save_inference_model(model_path, config): ...@@ -118,8 +117,8 @@ def _load_state_dict_from_save_inference_model(model_path, config):
def _load_state_dict_from_save_params(model_path): def _load_state_dict_from_save_params(model_path):
# Try to load all the files in the directory in VarBase format, # Try to load all the files in the directory in Tensor format,
# the file name is used as the name of VarBase # the file name is used as the name of Tensor
load_var_list = [] load_var_list = []
# 1. load file names # 1. load file names
...@@ -131,7 +130,7 @@ def _load_state_dict_from_save_params(model_path): ...@@ -131,7 +130,7 @@ def _load_state_dict_from_save_params(model_path):
var_name = tmp_var_name.replace("\\", "/") var_name = tmp_var_name.replace("\\", "/")
var_name_list.append(var_name) var_name_list.append(var_name)
# 2. create and load VarBase # 2. create and load Tensor
with fluid.dygraph.guard(): with fluid.dygraph.guard():
for name in var_name_list: for name in var_name_list:
new_var = _varbase_creator(name=name, persistable=True) new_var = _varbase_creator(name=name, persistable=True)
...@@ -320,17 +319,13 @@ def _pickle_save(obj, f, protocol): ...@@ -320,17 +319,13 @@ def _pickle_save(obj, f, protocol):
def add_dispatch_table(): def add_dispatch_table():
# This is not a good method, because the pickle module has been modified. # This is not a good method, because the pickle module has been modified.
pickle.dispatch_table[core.VarBase] = reduce_varbase
pickle.dispatch_table[ParamBase] = reduce_varbase
pickle.dispatch_table[core.eager.Tensor] = reduce_varbase pickle.dispatch_table[core.eager.Tensor] = reduce_varbase
pickle.dispatch_table[EagerParamBase] = reduce_varbase pickle.dispatch_table[EagerParamBase] = reduce_varbase
pickle.dispatch_table[core.LoDTensor] = reduce_LoDTensor pickle.dispatch_table[core.LoDTensor] = reduce_LoDTensor
pickle.dispatch_table.update(dispatch_table_layer) pickle.dispatch_table.update(dispatch_table_layer)
def pop_dispatch_table(): def pop_dispatch_table():
pickle.dispatch_table.pop(core.VarBase)
pickle.dispatch_table.pop(core.LoDTensor) pickle.dispatch_table.pop(core.LoDTensor)
pickle.dispatch_table.pop(ParamBase)
pickle.dispatch_table.pop(core.eager.Tensor) pickle.dispatch_table.pop(core.eager.Tensor)
pickle.dispatch_table.pop(EagerParamBase) pickle.dispatch_table.pop(EagerParamBase)
for k in dispatch_table_layer: for k in dispatch_table_layer:
...@@ -349,9 +344,7 @@ def _pickle_save(obj, f, protocol): ...@@ -349,9 +344,7 @@ def _pickle_save(obj, f, protocol):
pickler = pickle.Pickler(f, protocol) pickler = pickle.Pickler(f, protocol)
pickler.dispatch_table = copyreg.dispatch_table.copy() pickler.dispatch_table = copyreg.dispatch_table.copy()
pickler.dispatch_table[core.VarBase] = reduce_varbase
pickler.dispatch_table[core.LoDTensor] = reduce_LoDTensor pickler.dispatch_table[core.LoDTensor] = reduce_LoDTensor
pickler.dispatch_table[ParamBase] = reduce_varbase
pickler.dispatch_table[core.eager.Tensor] = reduce_varbase pickler.dispatch_table[core.eager.Tensor] = reduce_varbase
pickler.dispatch_table[EagerParamBase] = reduce_varbase pickler.dispatch_table[EagerParamBase] = reduce_varbase
pickler.dispatch_table.update(dispatch_table_layer) pickler.dispatch_table.update(dispatch_table_layer)
...@@ -390,24 +383,21 @@ def _is_state_dict(obj): ...@@ -390,24 +383,21 @@ def _is_state_dict(obj):
( (
paddle.nn.Layer, paddle.nn.Layer,
Program, Program,
core.VarBase,
core.eager.Tensor, core.eager.Tensor,
core.LoDTensor, core.LoDTensor,
core.SelectedRows, core.SelectedRows,
), ),
) )
# If the value of a dict is a core.VarBase/LoDTensor or a dict # If the value of a dict is a core.Tensor/LoDTensor or a dict
# that does not contain a paddle type(Layer, Program, VarBase, LoDTensor, SelectedRows), # that does not contain a paddle type(Layer, Program, Tensor, LoDTensor, SelectedRows),
# the dict is considered to be a state_ dict. # the dict is considered to be a state_ dict.
for key, value in obj.items(): for key, value in obj.items():
if isinstance(value, dict): if isinstance(value, dict):
for k, v in value.items(): for k, v in value.items():
if _contain_x(v, condition): if _contain_x(v, condition):
return False return False
elif not isinstance( elif not isinstance(value, (core.eager.Tensor, core.LoDTensor)):
value, (core.VarBase, core.eager.Tensor, core.LoDTensor)
):
return False return False
return True return True
...@@ -415,8 +405,8 @@ def _is_state_dict(obj): ...@@ -415,8 +405,8 @@ def _is_state_dict(obj):
def _transformed_from_varbase(obj): def _transformed_from_varbase(obj):
# In paddle2.1 version, VarBase is saved as tuple(tensor.name, tensor.numpy()). # In paddle2.1 version, Tensor is saved as tuple(tensor.name, tensor.numpy()).
# When executing paddle.load, use this function to determine whether to restore to VarBase/LoDTensor. # When executing paddle.load, use this function to determine whether to restore to Tensor/LoDTensor.
if isinstance(obj, tuple) and len(obj) == 2: if isinstance(obj, tuple) and len(obj) == 2:
name_types = str name_types = str
if isinstance(obj[0], name_types) and isinstance(obj[1], np.ndarray): if isinstance(obj[0], name_types) and isinstance(obj[1], np.ndarray):
...@@ -426,7 +416,7 @@ def _transformed_from_varbase(obj): ...@@ -426,7 +416,7 @@ def _transformed_from_varbase(obj):
def _transformed_from_lodtensor(obj): def _transformed_from_lodtensor(obj):
# In paddle2.1 version, LoDTensor is saved as np.array(tensor). # In paddle2.1 version, LoDTensor is saved as np.array(tensor).
# When executing paddle.load, use this function to determine whether to restore to VarBase/LoDTensor. # When executing paddle.load, use this function to determine whether to restore to Tensor/LoDTensor.
if isinstance(obj, np.ndarray): if isinstance(obj, np.ndarray):
return True return True
return False return False
...@@ -498,7 +488,7 @@ def _parse_every_object(obj, condition_func, convert_func): ...@@ -498,7 +488,7 @@ def _parse_every_object(obj, condition_func, convert_func):
else: else:
if isinstance(obj, Iterable) and not isinstance( if isinstance(obj, Iterable) and not isinstance(
obj, obj,
(str, np.ndarray, core.VarBase, core.eager.Tensor, core.LoDTensor), (str, np.ndarray, core.eager.Tensor, core.LoDTensor),
): ):
raise NotImplementedError( raise NotImplementedError(
"The iteratable objects supported are tuple, list, dict, OrderedDict, string. But received {}.".format( "The iteratable objects supported are tuple, list, dict, OrderedDict, string. But received {}.".format(
...@@ -642,7 +632,7 @@ def _save_binary_var(obj, path): ...@@ -642,7 +632,7 @@ def _save_binary_var(obj, path):
_save_lod_tensor(obj, path) _save_lod_tensor(obj, path)
elif isinstance(obj, core.SelectedRows): elif isinstance(obj, core.SelectedRows):
_save_selected_rows(obj, path) _save_selected_rows(obj, path)
elif isinstance(obj, (core.VarBase, core.eager.Tensor)): elif isinstance(obj, core.eager.Tensor):
_save_lod_tensor(obj.value().get_tensor(), path) _save_lod_tensor(obj.value().get_tensor(), path)
else: else:
# Since the concept of 'Tensor' is only exposed to users, the error message can only contain tensor instead of 'LoDTensor' or 'SelectedRows' # Since the concept of 'Tensor' is only exposed to users, the error message can only contain tensor instead of 'LoDTensor' or 'SelectedRows'
......
...@@ -180,7 +180,9 @@ def _load_program_scope(main=None, startup=None, scope=None): ...@@ -180,7 +180,9 @@ def _load_program_scope(main=None, startup=None, scope=None):
@static_only @static_only
def _legacy_static_save(param_dict, model_path, protocol=2): def _legacy_static_save(param_dict, model_path, protocol=2):
def get_tensor(var): def get_tensor(var):
if isinstance(var, (core.VarBase, core.eager.Tensor, core.LoDTensor)): if isinstance(var, core.eager.Tensor):
return np.array(var)
elif isinstance(var, core.LoDTensor):
return np.array(var) return np.array(var)
return var return var
......
...@@ -58,9 +58,9 @@ def to_list(value): ...@@ -58,9 +58,9 @@ def to_list(value):
def to_numpy(var): def to_numpy(var):
assert isinstance( assert isinstance(
var, (Variable, fluid.core.VarBase, fluid.core.eager.Tensor) var, (Variable, fluid.core.eager.Tensor)
), "not a variable" ), "not a variable"
if isinstance(var, (fluid.core.VarBase, fluid.core.eager.Tensor)): if isinstance(var, fluid.core.eager.Tensor):
return np.array(var) return np.array(var)
t = global_scope().find_var(var.name).get_tensor() t = global_scope().find_var(var.name).get_tensor()
return np.array(t) return np.array(t)
......
...@@ -261,7 +261,9 @@ def summary_string(model, input_size=None, dtypes=None, input=None): ...@@ -261,7 +261,9 @@ def summary_string(model, input_size=None, dtypes=None, input=None):
depth = len(list(model.sublayers())) depth = len(list(model.sublayers()))
def _get_shape_from_tensor(x): def _get_shape_from_tensor(x):
if isinstance(x, (paddle.fluid.Variable, paddle.fluid.core.VarBase)): if isinstance(
x, (paddle.fluid.Variable, paddle.fluid.core.eager.Tensor)
):
return list(x.shape) return list(x.shape)
elif isinstance(x, (list, tuple)): elif isinstance(x, (list, tuple)):
return [_get_shape_from_tensor(xx) for xx in x] return [_get_shape_from_tensor(xx) for xx in x]
......
...@@ -59,7 +59,6 @@ from paddle.nn import Layer ...@@ -59,7 +59,6 @@ from paddle.nn import Layer
from paddle.fluid.executor import Executor, scope_guard from paddle.fluid.executor import Executor, scope_guard
from paddle.fluid.framework import ( from paddle.fluid.framework import (
Block, Block,
ParamBase,
Program, Program,
Variable, Variable,
Parameter, Parameter,
...@@ -390,7 +389,7 @@ class _SaveLoadConfig: ...@@ -390,7 +389,7 @@ class _SaveLoadConfig:
% type(input) % type(input)
) )
for var in spec: for var in spec:
if not isinstance(var, core.VarBase): if not isinstance(var, core.eager.Tensor):
raise TypeError( raise TypeError(
"The element in config `output_spec` list should be 'Variable', but received element's type is %s." "The element in config `output_spec` list should be 'Variable', but received element's type is %s."
% type(var) % type(var)
...@@ -543,7 +542,7 @@ def _get_input_var_names(inputs, input_spec): ...@@ -543,7 +542,7 @@ def _get_input_var_names(inputs, input_spec):
# name is None, the input_spec only can be InputSpec # name is None, the input_spec only can be InputSpec
raise ValueError(name_none_error % spec) raise ValueError(name_none_error % spec)
elif spec.name not in input_var_names: elif spec.name not in input_var_names:
# the input_spec can be `InputSpec` or `VarBase` # the input_spec can be `InputSpec` or `Tensor`
raise ValueError(name_no_exists_error % spec.name) raise ValueError(name_no_exists_error % spec.name)
else: else:
result_list.append(spec.name) result_list.append(spec.name)
...@@ -973,7 +972,7 @@ def save(layer, path, input_spec=None, **configs): ...@@ -973,7 +972,7 @@ def save(layer, path, input_spec=None, **configs):
for var in paddle.utils.flatten(input_spec): for var in paddle.utils.flatten(input_spec):
if isinstance(var, paddle.static.InputSpec): if isinstance(var, paddle.static.InputSpec):
inner_input_spec.append(var) inner_input_spec.append(var)
elif isinstance(var, (core.VarBase, core.eager.Tensor, Variable)): elif isinstance(var, (core.eager.Tensor, Variable)):
inner_input_spec.append( inner_input_spec.append(
paddle.static.InputSpec.from_tensor(var) paddle.static.InputSpec.from_tensor(var)
) )
...@@ -1132,7 +1131,7 @@ def save(layer, path, input_spec=None, **configs): ...@@ -1132,7 +1131,7 @@ def save(layer, path, input_spec=None, **configs):
extra_info_dict[ extra_info_dict[
'stop_gradient' 'stop_gradient'
] = param_or_buffer.stop_gradient ] = param_or_buffer.stop_gradient
if isinstance(param_or_buffer, (ParamBase, EagerParamBase)): if isinstance(param_or_buffer, EagerParamBase):
extra_info_dict['trainable'] = param_or_buffer.trainable extra_info_dict['trainable'] = param_or_buffer.trainable
extra_var_info[param_or_buffer.name] = extra_info_dict extra_var_info[param_or_buffer.name] = extra_info_dict
...@@ -1151,7 +1150,7 @@ def save(layer, path, input_spec=None, **configs): ...@@ -1151,7 +1150,7 @@ def save(layer, path, input_spec=None, **configs):
# NOTE(chenweihang): [ Get output variables ] # NOTE(chenweihang): [ Get output variables ]
# the rule is like [ Get input variables name ]. For output var, # the rule is like [ Get input variables name ]. For output var,
# we only support VarBase spec, and actually, we only need the # we only support Tensor spec, and actually, we only need the
# var name of output, and we don't recommended to use output_spec # var name of output, and we don't recommended to use output_spec
# print(concrete_program.main_program) # print(concrete_program.main_program)
# print(concrete_program.outputs, configs.output_spec) # print(concrete_program.outputs, configs.output_spec)
......
...@@ -205,7 +205,7 @@ class ForNodeVisitor: ...@@ -205,7 +205,7 @@ class ForNodeVisitor:
In this process, the semantics of for does not change. In this process, the semantics of for does not change.
Now only can parse 3 type statements (Here var is VarBase(Tensor) or python variable): Now only can parse 3 type statements (Here var is Tensor(Tensor) or python variable):
1). for x in range(var[*]|var.numpy()[*]) 1). for x in range(var[*]|var.numpy()[*])
2). for x in var|var.numpy() 2). for x in var|var.numpy()
3). for i, x enumerate(var|var.numpy()) 3). for i, x enumerate(var|var.numpy())
......
...@@ -286,7 +286,7 @@ def _replace_value_with_input_spec(args): ...@@ -286,7 +286,7 @@ def _replace_value_with_input_spec(args):
if isinstance(input_var, np.ndarray): if isinstance(input_var, np.ndarray):
input_var = paddle.static.InputSpec.from_numpy(input_var) input_var = paddle.static.InputSpec.from_numpy(input_var)
input_var.stop_gradient = True input_var.stop_gradient = True
elif isinstance(input_var, (core.VarBase, core.eager.Tensor)): elif isinstance(input_var, core.eager.Tensor):
stop_gradient = input_var.stop_gradient stop_gradient = input_var.stop_gradient
input_var = paddle.static.InputSpec.from_tensor(input_var) input_var = paddle.static.InputSpec.from_tensor(input_var)
input_var.stop_gradient = stop_gradient input_var.stop_gradient = stop_gradient
...@@ -341,7 +341,7 @@ def convert_to_input_spec(inputs, input_spec): ...@@ -341,7 +341,7 @@ def convert_to_input_spec(inputs, input_spec):
# without specific InputSpec, raise warning. # without specific InputSpec, raise warning.
if len(inputs) > len(input_spec): if len(inputs) > len(input_spec):
for rest_input in inputs[len(input_spec) :]: for rest_input in inputs[len(input_spec) :]:
if isinstance(rest_input, (core.VarBase, np.ndarray)): if isinstance(rest_input, (core.eager.Tensor, np.ndarray)):
logging_utils.warn( logging_utils.warn(
"The inputs constain `{}` without specificing InputSpec, its shape and dtype will be treated immutable. " "The inputs constain `{}` without specificing InputSpec, its shape and dtype will be treated immutable. "
"Please specific InputSpec information in `@to_static` if you expect them as mutable inputs.".format( "Please specific InputSpec information in `@to_static` if you expect them as mutable inputs.".format(
......
...@@ -59,9 +59,7 @@ class NestSequence: ...@@ -59,9 +59,7 @@ class NestSequence:
def _get_var_ids(self): def _get_var_ids(self):
var_ids = [] var_ids = []
for idx, var in enumerate(self.__input_list): for idx, var in enumerate(self.__input_list):
if isinstance( if isinstance(var, (framework.Variable, core.eager.Tensor)):
var, (framework.Variable, core.VarBase, core.eager.Tensor)
):
var_ids.append(idx) var_ids.append(idx)
return var_ids return var_ids
...@@ -73,9 +71,7 @@ class NestSequence: ...@@ -73,9 +71,7 @@ class NestSequence:
if need_check: if need_check:
warning_types = set() warning_types = set()
for var in self.__input_list: for var in self.__input_list:
if not isinstance( if not isinstance(var, (framework.Variable, core.eager.Tensor)):
var, (framework.Variable, core.VarBase, core.eager.Tensor)
):
warning_types.add(type(var)) warning_types.add(type(var))
if warning_types: if warning_types:
logging_utils.warn( logging_utils.warn(
...@@ -161,7 +157,7 @@ class PartialProgramLayer: ...@@ -161,7 +157,7 @@ class PartialProgramLayer:
main_program(Program): The main program that contains ops need to be executed. main_program(Program): The main program that contains ops need to be executed.
inputs(list[Variable]): The input list of the decorated function by `@to_static`. inputs(list[Variable]): The input list of the decorated function by `@to_static`.
outputs(list[Variable]): The output list of the decorated function by `@to_static`. outputs(list[Variable]): The output list of the decorated function by `@to_static`.
parameters(list[VarBase]|None): All trainable parameters included in the program. Default None. parameters(list[Tensor]|None): All trainable parameters included in the program. Default None.
Returns: Returns:
Layer: A Layer object that run all ops internally in static graph mode. Layer: A Layer object that run all ops internally in static graph mode.
...@@ -669,22 +665,13 @@ class PartialProgramLayer: ...@@ -669,22 +665,13 @@ class PartialProgramLayer:
if "@GRAD" in name: if "@GRAD" in name:
var_desc = block.vars[name].desc var_desc = block.vars[name].desc
var_base = None var_base = None
if not framework.global_var._in_eager_mode_: var_base = core.eager.Tensor(
var_base = core.VarBase( var_desc.dtype(),
var_desc.dtype(), var_desc.shape(),
var_desc.shape(), var_desc.name(),
var_desc.name(), var_desc.type(),
var_desc.type(), False,
False, )
)
else:
var_base = core.eager.Tensor(
var_desc.dtype(),
var_desc.shape(),
var_desc.name(),
var_desc.type(),
False,
)
double_grads.append(var_base) double_grads.append(var_base)
return self._valid_vars(double_grads) return self._valid_vars(double_grads)
...@@ -866,29 +853,20 @@ class PartialProgramLayer: ...@@ -866,29 +853,20 @@ class PartialProgramLayer:
assert isinstance(inputs, (tuple, list)) assert isinstance(inputs, (tuple, list))
# Flatten inputs with nested structure into single list. # Flatten inputs with nested structure into single list.
flatten_inputs = paddle.utils.flatten(inputs) flatten_inputs = paddle.utils.flatten(inputs)
# Convert variable into VarBase and feed in training data. # Convert variable into Tensor and feed in training data.
input_vars = [] input_vars = []
expected_place = framework._current_expected_place() expected_place = framework._current_expected_place()
for i, value in enumerate(flatten_inputs): for i, value in enumerate(flatten_inputs):
if isinstance(value, np.ndarray): if isinstance(value, np.ndarray):
var = None var = None
if not framework.global_var._in_eager_mode_: var = core.eager.Tensor(
var = core.VarBase( value=value,
value=value, name=self._inputs[i].desc.name(),
name=self._inputs[i].desc.name(), persistable=False,
persistable=False, place=expected_place,
place=expected_place, zero_copy=True,
zero_copy=True, )
) elif isinstance(value, core.eager.Tensor):
else:
var = core.eager.Tensor(
value=value,
name=self._inputs[i].desc.name(),
persistable=False,
place=expected_place,
zero_copy=True,
)
elif isinstance(value, (core.VarBase, core.eager.Tensor)):
# NOTE(Aurelius84): If var is on CPUPlace, it will be transformed multi times # NOTE(Aurelius84): If var is on CPUPlace, it will be transformed multi times
# into CUDAPlace when it's as input of multi Ops. so we move it in advance # into CUDAPlace when it's as input of multi Ops. so we move it in advance
# to avoid this problem. # to avoid this problem.
...@@ -904,7 +882,7 @@ class PartialProgramLayer: ...@@ -904,7 +882,7 @@ class PartialProgramLayer:
continue continue
input_vars.append(var) input_vars.append(var)
# mapping from name(string) -> VarBase # mapping from name(string) -> Tensor
out_varbase_map = {} out_varbase_map = {}
def create_out(var_id): def create_out(var_id):
...@@ -916,27 +894,18 @@ class PartialProgramLayer: ...@@ -916,27 +894,18 @@ class PartialProgramLayer:
if var_desc.name() in out_varbase_map: if var_desc.name() in out_varbase_map:
return out_varbase_map[var_desc.name()] return out_varbase_map[var_desc.name()]
if not framework.global_var._in_eager_mode_: var_base = core.eager.Tensor(
var_base = core.VarBase( var_desc.dtype(),
var_desc.dtype(), var_desc.shape(),
var_desc.shape(), var_desc.name(),
var_desc.name(), var_desc.type(),
var_desc.type(), False,
False, )
)
else:
var_base = core.eager.Tensor(
var_desc.dtype(),
var_desc.shape(),
var_desc.name(),
var_desc.type(),
False,
)
var_base.stop_gradient = var.stop_gradient var_base.stop_gradient = var.stop_gradient
out_varbase_map[var_desc.name()] = var_base out_varbase_map[var_desc.name()] = var_base
return var_base return var_base
# Create VarBase to receive output data. # Create Tensor to receive output data.
out_vars = list(map(create_out, self._outputs.var_ids)) out_vars = list(map(create_out, self._outputs.var_ids))
return input_vars, out_vars return input_vars, out_vars
...@@ -947,21 +916,11 @@ class PartialProgramLayer: ...@@ -947,21 +916,11 @@ class PartialProgramLayer:
inner_scope = self._get_scope( inner_scope = self._get_scope(
program_id=program_id, use_scope_cache=use_scope_cache program_id=program_id, use_scope_cache=use_scope_cache
) )
if not framework.global_var._in_eager_mode_: tmp_scope_vec = [inner_scope]
tmp_scope_vec = core.VarBase(
core.VarDesc.VarType.FP32,
[],
"program_out_scope",
core.VarDesc.VarType.STEP_SCOPES,
True,
)
tmp_scope_vec.value().set_scope(inner_scope)
else:
tmp_scope_vec = [inner_scope]
return tmp_scope_vec return tmp_scope_vec
def _create_cuda_graph_vec(self): def _create_cuda_graph_vec(self):
var = core.VarBase( var = core.eager.Tensor(
core.VarDesc.VarType.FP32, core.VarDesc.VarType.FP32,
[], [],
"cuda_graph", "cuda_graph",
...@@ -973,7 +932,7 @@ class PartialProgramLayer: ...@@ -973,7 +932,7 @@ class PartialProgramLayer:
def _restore_out(self, out_vars): def _restore_out(self, out_vars):
""" """
Restores same nested outputs by only replacing the Variable with VarBase. Restores same nested outputs by only replacing the Variable with Tensor.
""" """
flatten_outputs = self._outputs.tolist() flatten_outputs = self._outputs.tolist()
...@@ -990,9 +949,7 @@ class PartialProgramLayer: ...@@ -990,9 +949,7 @@ class PartialProgramLayer:
return main_program.clone(for_test=True) return main_program.clone(for_test=True)
def _is_no_value(self, var): def _is_no_value(self, var):
if isinstance(var, (core.VarBase, core.eager.Tensor)) and var.shape == [ if isinstance(var, core.eager.Tensor) and var.shape == [1]:
1
]:
# NOTE: .numpy() will insert MemcpySync operation, it hits performance. # NOTE: .numpy() will insert MemcpySync operation, it hits performance.
if var.numpy()[0] == RETURN_NO_VALUE_MAGIC_NUM: if var.numpy()[0] == RETURN_NO_VALUE_MAGIC_NUM:
return True return True
...@@ -1002,7 +959,7 @@ class PartialProgramLayer: ...@@ -1002,7 +959,7 @@ class PartialProgramLayer:
""" """
Removes invalid value for various-length return statement Removes invalid value for various-length return statement
""" """
if isinstance(out_vars, (core.VarBase, core.eager.Tensor)): if isinstance(out_vars, core.eager.Tensor):
if self._is_no_value(out_vars): if self._is_no_value(out_vars):
return None return None
return out_vars return out_vars
...@@ -1029,7 +986,7 @@ class PartialProgramLayer: ...@@ -1029,7 +986,7 @@ class PartialProgramLayer:
def _set_grad_type(self, params, train_program): def _set_grad_type(self, params, train_program):
# NOTE: if user set sparse gradient mode, the param's gradient # NOTE: if user set sparse gradient mode, the param's gradient
# will be SelectedRows, not LoDTensor. But tracer will just # will be SelectedRows, not LoDTensor. But tracer will just
# set param grad VarBase by forward VarBase(LoDTensor) # set param grad Tensor by forward Tensor(LoDTensor)
# If we don't change grad_var type here, RunProgramOp need # If we don't change grad_var type here, RunProgramOp need
# transform SelectedRows to LoDTensor forcibly, it may not # transform SelectedRows to LoDTensor forcibly, it may not
# be user wanted result. # be user wanted result.
...@@ -1057,9 +1014,9 @@ class PartialProgramLayer: ...@@ -1057,9 +1014,9 @@ class PartialProgramLayer:
def _check_params_all_inited(self, main_program): def _check_params_all_inited(self, main_program):
""" """
Check all params from main program are already initialized, see details as follows: Check all params from main program are already initialized, see details as follows:
1. all parameters in self._params should be type `framework.ParamBase` which are created in dygraph. 1. all parameters in self._params should be type `framework.EagerParamBase` which are created in dygraph.
2. all parameters from transformed program can be found in self._params. 2. all parameters from transformed program can be found in self._params.
Because they share same data with ParamBase of original dygraph. Because they share same data with EagerParamBase of original dygraph.
""" """
if not isinstance(self._params, (list, tuple)): if not isinstance(self._params, (list, tuple)):
raise TypeError( raise TypeError(
...@@ -1070,7 +1027,7 @@ class PartialProgramLayer: ...@@ -1070,7 +1027,7 @@ class PartialProgramLayer:
param_and_buffer_names_set = set() param_and_buffer_names_set = set()
for i, var in enumerate(self._params): for i, var in enumerate(self._params):
# self._params constains parameters and buffers with persistable=True. # self._params constains parameters and buffers with persistable=True.
if not isinstance(var, (core.VarBase, core.eager.Tensor)): if not isinstance(var, core.eager.Tensor):
raise TypeError( raise TypeError(
'Type of self._params[{}] in PartialProgramLayer should be Parameter or Variable, but received {}.'.format( 'Type of self._params[{}] in PartialProgramLayer should be Parameter or Variable, but received {}.'.format(
i, type(var) i, type(var)
......
...@@ -648,22 +648,13 @@ def _load_persistable_vars_by_program( ...@@ -648,22 +648,13 @@ def _load_persistable_vars_by_program(
orig_each_name = program_holder._suffix_varname_dict[each_var.name()] orig_each_name = program_holder._suffix_varname_dict[each_var.name()]
if _is_parameter(each_var, program_holder.infer_program): if _is_parameter(each_var, program_holder.infer_program):
# create output varbase # create output varbase
if framework._in_eager_without_dygraph_check(): new_var = framework.EagerParamBase(
new_var = framework.EagerParamBase( shape=each_var.shape(),
shape=each_var.shape(), dtype=each_var.dtype(),
dtype=each_var.dtype(), name=each_var.name(),
name=each_var.name(), type=each_var.type(),
type=each_var.type(), persistable=True,
persistable=True, )
)
else:
new_var = framework.ParamBase(
shape=each_var.shape(),
dtype=each_var.dtype(),
name=each_var.name(),
type=each_var.type(),
persistable=True,
)
else: else:
new_var = framework._varbase_creator( new_var = framework._varbase_creator(
type=each_var.type(), type=each_var.type(),
...@@ -746,24 +737,12 @@ def _load_persistable_vars( ...@@ -746,24 +737,12 @@ def _load_persistable_vars(
# create output varbase # create output varbase
if extra_var_info[name].get('trainable', None) is not None: if extra_var_info[name].get('trainable', None) is not None:
# use default shape and dtype # use default shape and dtype
if framework._in_eager_without_dygraph_check(): new_var = framework.EagerParamBase(
new_var = framework.EagerParamBase( shape=[1], # only to pass check, this shape is not meaningful
shape=[ dtype=core.VarDesc.VarType.FP32,
1 name=new_name,
], # only to pass check, this shape is not meaningful persistable=True,
dtype=core.VarDesc.VarType.FP32, )
name=new_name,
persistable=True,
)
else:
new_var = framework.ParamBase(
shape=[
1
], # only to pass check, this shape is not meaningful
dtype=core.VarDesc.VarType.FP32,
name=new_name,
persistable=True,
)
else: else:
new_var = framework._varbase_creator( new_var = framework._varbase_creator(
name=new_name, persistable=True name=new_name, persistable=True
...@@ -901,29 +880,20 @@ def _run_dygraph(instance, input, program_holder): ...@@ -901,29 +880,20 @@ def _run_dygraph(instance, input, program_holder):
# 1. prepare inputs, outputs, attrs # 1. prepare inputs, outputs, attrs
input_vars = [] input_vars = []
for i, value in enumerate(input): for i, value in enumerate(input):
if not isinstance(value, (np.ndarray, core.VarBase, core.eager.Tensor)): if not isinstance(value, (np.ndarray, core.eager.Tensor)):
raise TypeError( raise TypeError(
"The type of input in TranslatedLayer must be numpy array or Variable(VarBase), but received %s." "The type of input in TranslatedLayer must be numpy array or Variable(Tensor), but received %s."
% type(value) % type(value)
) )
# NOTE: In order to unify the API, firstly convert the input to VarBase # NOTE: In order to unify the API, firstly convert the input to Tensor
if isinstance(value, np.ndarray): if isinstance(value, np.ndarray):
if framework._in_eager_without_dygraph_check(): var = core.eager.Tensor(
var = core.eager.Tensor( value=value,
value=value, name=program_holder.input_descs[i].name(),
name=program_holder.input_descs[i].name(), persistable=False,
persistable=False, place=framework._current_expected_place(),
place=framework._current_expected_place(), zero_copy=True,
zero_copy=True, )
)
else:
var = core.VarBase(
value=value,
name=program_holder.input_descs[i].name(),
persistable=False,
place=framework._current_expected_place(),
zero_copy=True,
)
else: else:
var = value var = value
# NOTE: we changed var name here, # NOTE: we changed var name here,
...@@ -950,55 +920,27 @@ def _run_dygraph(instance, input, program_holder): ...@@ -950,55 +920,27 @@ def _run_dygraph(instance, input, program_holder):
output_vars = [] output_vars = []
for var_desc in program_holder.output_descs: for var_desc in program_holder.output_descs:
if framework._in_eager_without_dygraph_check(): var = core.eager.Tensor(
var = core.eager.Tensor( dtype=var_desc.dtype(),
dtype=var_desc.dtype(), dims=var_desc.shape(),
dims=var_desc.shape(), name=var_desc.name(),
name=var_desc.name(), type=var_desc.type(),
type=var_desc.type(), persistable=False,
persistable=False, )
)
else:
var = core.VarBase(
var_desc.dtype(),
var_desc.shape(),
var_desc.name(),
var_desc.type(),
False,
)
output_vars.append(var) output_vars.append(var)
# hold forward variables # hold forward variables
if framework._in_eager_without_dygraph_check(): tmp_scope_vec = [program_holder.scope]
tmp_scope_vec = [program_holder.scope]
else:
tmp_scope_vec = core.VarBase(
core.VarDesc.VarType.FP32,
[],
"program_out_scope",
core.VarDesc.VarType.STEP_SCOPES,
True,
)
tmp_scope_vec.value().set_scope(program_holder.scope)
double_grad_vars = [] double_grad_vars = []
for var_desc in program_holder.double_grad_descs: for var_desc in program_holder.double_grad_descs:
if framework._in_eager_without_dygraph_check(): var = core.eager.Tensor(
var = core.eager.Tensor( dtype=var_desc.dtype(),
dtype=var_desc.dtype(), dims=var_desc.shape(),
dims=var_desc.shape(), name=var_desc.name(),
name=var_desc.name(), type=var_desc.type(),
type=var_desc.type(), persistable=False,
persistable=False, )
)
else:
var = core.VarBase(
var_desc.dtype(),
var_desc.shape(),
var_desc.name(),
var_desc.type(),
False,
)
double_grad_vars.append(var) double_grad_vars.append(var)
# 2. run program by op # 2. run program by op
...@@ -1064,7 +1006,7 @@ def _run_dygraph(instance, input, program_holder): ...@@ -1064,7 +1006,7 @@ def _run_dygraph(instance, input, program_holder):
# NOTE: [ why need set param's gradient type here ] # NOTE: [ why need set param's gradient type here ]
# if user set sparse gradient mode, the param's gradient # if user set sparse gradient mode, the param's gradient
# will be SelectedRows, not LoDTensor. But tracer will just # will be SelectedRows, not LoDTensor. But tracer will just
# set param grad VarBase by forward VarBase(LoDTensor) # set param grad Tensor by forward Tensor(LoDTensor)
# If we don't change grad_var type here, RunProgramOp need # If we don't change grad_var type here, RunProgramOp need
# transform SelectedRows to LoDTensor forcibly, it may not # transform SelectedRows to LoDTensor forcibly, it may not
# be user wanted result. # be user wanted result.
...@@ -1454,20 +1396,18 @@ class TranslatedLayer(layers.Layer): ...@@ -1454,20 +1396,18 @@ class TranslatedLayer(layers.Layer):
# When add parameter or buffer to Layer by follow apis, # When add parameter or buffer to Layer by follow apis,
# the variable name can't contain `.`, beccause which may cause # the variable name can't contain `.`, beccause which may cause
# AttributeError when access the newly added parameter or buffer # AttributeError when access the newly added parameter or buffer
# in the form of `self.**.**``, but the ParamBase or BarBase # in the form of `self.**.**``, but the EagerParamBase or BarBase
# name contains `.` originally, such as `linear_0.w_0`, so here # name contains `.` originally, such as `linear_0.w_0`, so here
# need to generate new var name for each var # need to generate new var name for each var
self._persistable_var_name_dict = {} self._persistable_var_name_dict = {}
# the TranslatedLayer object holded var names count started from 0 # the TranslatedLayer object holded var names count started from 0
with unique_name.guard(): with unique_name.guard():
for name, var in persistable_vars.items(): for name, var in persistable_vars.items():
if isinstance( if isinstance(var, framework.EagerParamBase):
var, (framework.ParamBase, framework.EagerParamBase)
):
dy_name = _generate_unique_var_name(PARAMETER_NAME_PREFIX) dy_name = _generate_unique_var_name(PARAMETER_NAME_PREFIX)
self._persistable_var_name_dict[name] = dy_name self._persistable_var_name_dict[name] = dy_name
self.add_parameter(dy_name, var) self.add_parameter(dy_name, var)
elif isinstance(var, (core.VarBase, core.eager.Tensor)): elif isinstance(var, core.eager.Tensor):
dy_name = _generate_unique_var_name(BUFFER_NAME_PREFIX) dy_name = _generate_unique_var_name(BUFFER_NAME_PREFIX)
self._persistable_var_name_dict[name] = dy_name self._persistable_var_name_dict[name] = dy_name
self.register_buffer(dy_name, var) self.register_buffer(dy_name, var)
......
...@@ -1069,9 +1069,7 @@ class Layer: ...@@ -1069,9 +1069,7 @@ class Layer:
raise KeyError("The name of buffer can not be empty.") raise KeyError("The name of buffer can not be empty.")
elif hasattr(self, name) and name not in self._buffers: elif hasattr(self, name) and name not in self._buffers:
raise KeyError("attribute '{}' already exists.".format(name)) raise KeyError("attribute '{}' already exists.".format(name))
elif tensor is not None and not ( elif tensor is not None and not (type(tensor) == core.eager.Tensor):
type(tensor) == core.VarBase or type(tensor) == core.eager.Tensor
):
raise TypeError( raise TypeError(
"The registered buffer should be a Paddle.Tensor, but received {}.".format( "The registered buffer should be a Paddle.Tensor, but received {}.".format(
type(tensor).__name__ type(tensor).__name__
...@@ -1524,7 +1522,7 @@ class Layer: ...@@ -1524,7 +1522,7 @@ class Layer:
layers[name] = None layers[name] = None
else: else:
_buffers = self.__dict__.get('_buffers', None) _buffers = self.__dict__.get('_buffers', None)
if isinstance(value, (core.VarBase, core.eager.Tensor)): if isinstance(value, core.eager.Tensor):
if _buffers is None: if _buffers is None:
raise ValueError( raise ValueError(
"super().__init__() should be called first" "super().__init__() should be called first"
...@@ -1559,14 +1557,14 @@ class Layer: ...@@ -1559,14 +1557,14 @@ class Layer:
) )
elif ( elif (
_buffers[name] is None _buffers[name] is None
or type(getattr(self, name)) == core.VarBase or type(getattr(self, name)) == core.eager.Tensor
): ):
_buffers[name] = assign(value) _buffers[name] = assign(value)
else: else:
assign(value, getattr(self, name)) assign(value, getattr(self, name))
elif value is not None: elif value is not None:
raise TypeError( raise TypeError(
"assignment to buffers '{}' should be of type core.VarBase or None, but got '{}'".format( "assignment to buffers '{}' should be of type core.Tensor or None, but got '{}'".format(
name, type(value).__name__ name, type(value).__name__
) )
) )
......
...@@ -383,7 +383,7 @@ class Optimizer: ...@@ -383,7 +383,7 @@ class Optimizer:
if isinstance(load_para, Variable): if isinstance(load_para, Variable):
load_para_np = np.array(load_para) load_para_np = np.array(load_para)
elif isinstance(load_para, core.VarBase): elif isinstance(load_para, core.eager.Tensor):
load_para_np = np.array(load_para) load_para_np = np.array(load_para)
elif isinstance(load_para, np.ndarray): elif isinstance(load_para, np.ndarray):
load_para_np = load_para load_para_np = load_para
......
...@@ -195,7 +195,7 @@ class InputSpec: ...@@ -195,7 +195,7 @@ class InputSpec:
print(x_spec) # InputSpec(shape=(2, 2), dtype=paddle.float32, name=x) print(x_spec) # InputSpec(shape=(2, 2), dtype=paddle.float32, name=x)
""" """
if isinstance(tensor, (Variable, core.VarBase, core.eager.Tensor)): if isinstance(tensor, (Variable, core.eager.Tensor)):
return cls(tensor.shape, tensor.dtype, name or tensor.name) return cls(tensor.shape, tensor.dtype, name or tensor.name)
else: else:
raise ValueError( raise ValueError(
......
...@@ -368,7 +368,7 @@ def assign_skip_lod_tensor_array(input, output): ...@@ -368,7 +368,7 @@ def assign_skip_lod_tensor_array(input, output):
return True return True
return False return False
if not isinstance(input, (Variable, core.VarBase)): if not isinstance(input, (Variable, core.eager.Tensor)):
if isinstance(output, Variable) and isinstance( if isinstance(output, Variable) and isinstance(
input, support_ret_buildin_type input, support_ret_buildin_type
): ):
......
...@@ -28,7 +28,6 @@ from imperative_test_utils import ( ...@@ -28,7 +28,6 @@ from imperative_test_utils import (
import paddle import paddle
from paddle import nn from paddle import nn
from paddle.dataset.common import download from paddle.dataset.common import download
from paddle.fluid.framework import _test_eager_guard
from paddle.quantization import ( from paddle.quantization import (
AbsmaxQuantizer, AbsmaxQuantizer,
HistQuantizer, HistQuantizer,
...@@ -266,8 +265,6 @@ class TestImperativePTQ(unittest.TestCase): ...@@ -266,8 +265,6 @@ class TestImperativePTQ(unittest.TestCase):
print("total time: %ss \n" % (end_time - start_time)) print("total time: %ss \n" % (end_time - start_time))
def test_ptq(self): def test_ptq(self):
with _test_eager_guard():
self.func_ptq()
self.func_ptq() self.func_ptq()
...@@ -339,8 +336,6 @@ class TestImperativePTQfuse(TestImperativePTQ): ...@@ -339,8 +336,6 @@ class TestImperativePTQfuse(TestImperativePTQ):
print("total time: %ss \n" % (end_time - start_time)) print("total time: %ss \n" % (end_time - start_time))
def test_ptq(self): def test_ptq(self):
with _test_eager_guard():
self.func_ptq()
self.func_ptq() self.func_ptq()
......
...@@ -20,7 +20,6 @@ import numpy as np ...@@ -20,7 +20,6 @@ import numpy as np
import paddle import paddle
from paddle import nn from paddle import nn
from paddle.fluid.framework import _test_eager_guard
from paddle.nn import Sequential from paddle.nn import Sequential
from paddle.optimizer import Adam from paddle.optimizer import Adam
from paddle.quantization import ImperativeQuantAware from paddle.quantization import ImperativeQuantAware
...@@ -262,8 +261,6 @@ class TestUserDefinedActPreprocess(unittest.TestCase): ...@@ -262,8 +261,6 @@ class TestUserDefinedActPreprocess(unittest.TestCase):
test(lenet) test(lenet)
def test_quant_aware_training(self): def test_quant_aware_training(self):
with _test_eager_guard():
self.func_quant_aware_training()
self.func_quant_aware_training() self.func_quant_aware_training()
......
...@@ -570,7 +570,7 @@ def _to_tensor_non_static(data, dtype=None, place=None, stop_gradient=True): ...@@ -570,7 +570,7 @@ def _to_tensor_non_static(data, dtype=None, place=None, stop_gradient=True):
return data return data
elif isinstance(data, (core.LoDTensor, core.Tensor)): elif isinstance(data, (core.LoDTensor, core.Tensor)):
# should't expose it to users, just for internal use. # should't expose it to users, just for internal use.
# convert core.Tensor/core.LoDTensor to VarBase first # convert core.Tensor/core.LoDTensor to Tensor first
# Currenly, there is no copy when places are same # Currenly, there is no copy when places are same
if in_dygraph_mode(): if in_dygraph_mode():
data = core.eager.Tensor(data) data = core.eager.Tensor(data)
...@@ -2023,12 +2023,12 @@ def assign(x, output=None): ...@@ -2023,12 +2023,12 @@ def assign(x, output=None):
input = np.array([input]) input = np.array([input])
elif isinstance(input, (list, tuple)): elif isinstance(input, (list, tuple)):
input = np.array(input) input = np.array(input)
# NOTE(Aurelius84): Why we judge core.VarBase? # NOTE(Aurelius84): Why we judge core.Tensor?
# In case of @to_static, a VarBase can be as input of `assign`, # In case of @to_static, a Tensor can be as input of `assign`,
# but _non_static_mode()==False under @to_static, which means # but _non_static_mode()==False under @to_static, which means
# isinstance(VarBase, Variable) == False. It will cause return None # isinstance(Tensor, Variable) == False. It will cause return None
# after this api. # after this api.
if isinstance(input, (Variable, core.VarBase, core.eager.Tensor)): if isinstance(input, (Variable, core.eager.Tensor)):
if in_dygraph_mode(): if in_dygraph_mode():
if output is None: if output is None:
output = _C_ops.assign(input) output = _C_ops.assign(input)
...@@ -2208,7 +2208,7 @@ def _memcpy(input, place=None, output=None): ...@@ -2208,7 +2208,7 @@ def _memcpy(input, place=None, output=None):
helper = LayerHelper('memcpy', **locals()) helper = LayerHelper('memcpy', **locals())
check_type(input, 'input', (Variable), 'memcpy') check_type(input, 'input', (Variable), 'memcpy')
if isinstance(input, (Variable, core.VarBase)): if isinstance(input, (Variable, core.eager.Tensor)):
check_dtype( check_dtype(
input.dtype, input.dtype,
'input', 'input',
......
...@@ -18,13 +18,9 @@ import paddle ...@@ -18,13 +18,9 @@ import paddle
from ..common_ops_import import Variable from ..common_ops_import import Variable
from ..fluid.data_feeder import check_type, check_variable_and_dtype from ..fluid.data_feeder import check_type, check_variable_and_dtype
from ..fluid.framework import global_var
from .layer_function_generator import templatedoc from .layer_function_generator import templatedoc
if global_var._in_eager_mode_: Tensor = paddle.fluid.framework.core.eager.Tensor
Tensor = paddle.fluid.framework.core.eager.Tensor
else:
from ..framework import VarBase as Tensor
from paddle import _C_ops from paddle import _C_ops
from paddle.tensor.creation import full from paddle.tensor.creation import full
......
...@@ -4758,5 +4758,4 @@ __METHODS = { ...@@ -4758,5 +4758,4 @@ __METHODS = {
'tolist': tolist, 'tolist': tolist,
} }
for name, func in __METHODS.items(): for name, func in __METHODS.items():
setattr(core.VarBase, name, func)
setattr(core.eager.Tensor, name, func) setattr(core.eager.Tensor, name, func)
...@@ -1082,7 +1082,7 @@ def _custom_api_content(op_name): ...@@ -1082,7 +1082,7 @@ def _custom_api_content(op_name):
API_TEMPLATE = textwrap.dedent( API_TEMPLATE = textwrap.dedent(
""" """
import paddle.fluid.core as core import paddle.fluid.core as core
from paddle.fluid.core import VarBase, CustomOpKernelContext from paddle.fluid.core import Tensor, CustomOpKernelContext
from paddle.fluid.framework import _dygraph_tracer, in_dygraph_mode from paddle.fluid.framework import _dygraph_tracer, in_dygraph_mode
from paddle.fluid.layer_helper import LayerHelper from paddle.fluid.layer_helper import LayerHelper
......
...@@ -459,22 +459,6 @@ if [ "${UNITTEST_FILE_CHANGED}" != "" ] && [ "${GIT_PR_ID}" != "" ]; then ...@@ -459,22 +459,6 @@ if [ "${UNITTEST_FILE_CHANGED}" != "" ] && [ "${GIT_PR_ID}" != "" ]; then
fi fi
fi fi
if [ "${UNITTEST_FILE_CHANGED}" != "" ] && [ "${GIT_PR_ID}" != "" ]; then
ERROR_LINES=""
for TEST_FILE in ${UNITTEST_FILE_CHANGED};
do
ENABLE_LEGACY_DYGRAPH_CI=`git diff -U0 upstream/$BRANCH ${PADDLE_ROOT}/${TEST_FILE} |grep "_enable_legacy_dygraph" || true`
if [ "${ENABLE_LEGACY_DYGRAPH_CI}" != "" ]; then
ERROR_LINES="${ERROR_LINES}\n${TEST_FILE}\n${ENABLE_LEGACY_DYGRAPH_CI}\n"
fi
done
if [ "${ERROR_LINES}" != "" ]; then
ERROR_LINES=${ERROR_LINES//+/'\n+\t'}
echo_line="_enable_legacy_dygraph forces the mode to old dynamic graph. You must have one RD (pangyoki (Recommend), Aurelius84 or JiabinYang) approval for the usage (either add or delete) of _enable_legacy_dygraph. For more information, please refer to: https://github.com/PaddlePaddle/Paddle/wiki/Enable-Eager-Mode-in-Paddle-CI. The corresponding lines are as follows:\n${ERROR_LINES}\n"
check_approval 1 26408901 9301846 22361972
fi
fi
RUNTYPE_FILE_CHANGED=`git diff --name-only --diff-filter=AM upstream/$BRANCH|grep -E "CMakeLists.txt"||true` RUNTYPE_FILE_CHANGED=`git diff --name-only --diff-filter=AM upstream/$BRANCH|grep -E "CMakeLists.txt"||true`
if [ "${RUNTYPE_FILE_CHANGED}" != "" ] && [ "${GIT_PR_ID}" != "" ]; then if [ "${RUNTYPE_FILE_CHANGED}" != "" ] && [ "${GIT_PR_ID}" != "" ]; then
for CMAKELISTS_FILE in ${RUNTYPE_FILE_CHANGED}; for CMAKELISTS_FILE in ${RUNTYPE_FILE_CHANGED};
......
...@@ -54,7 +54,7 @@ def split_with_and_without_core_ops(member, cur_name): ...@@ -54,7 +54,7 @@ def split_with_and_without_core_ops(member, cur_name):
return return
if ( if (
cur_name.find('ParamBase') != -1 cur_name.find('EagerParamBase') != -1
or cur_name.find('Parameter') != -1 or cur_name.find('Parameter') != -1
or cur_name.find('Variable') != -1 or cur_name.find('Variable') != -1
or cur_name.find('control_flow') != -1 or cur_name.find('control_flow') != -1
......
...@@ -156,8 +156,8 @@ def get_op_list(op_list_file='list_op.txt'): ...@@ -156,8 +156,8 @@ def get_op_list(op_list_file='list_op.txt'):
def set_diff_value(file, atol="1e-5", inplace_atol="1e-7"): def set_diff_value(file, atol="1e-5", inplace_atol="1e-7"):
""" """
:param file: refer to op_test.py :param file: refer to eager_op_test.py
:param atol: refer to op_test.py :param atol: refer to eager_op_test.py
:param inplace_atol: :param inplace_atol:
:return: :return:
""" """
...@@ -269,8 +269,8 @@ def run_test_first(op_list_file): ...@@ -269,8 +269,8 @@ def run_test_first(op_list_file):
""" """
old_list = get_op_list(op_list_file) old_list = get_op_list(op_list_file)
new_list = filter(lambda x: x not in black_list, old_list) new_list = filter(lambda x: x not in black_list, old_list)
op_test = transform_list_to_str(new_list) eager_op_test = transform_list_to_str(new_list)
os.system("ctest -R \"(" + op_test + ")\" >& test_op_log.txt") os.system("ctest -R \"(" + eager_op_test + ")\" >& test_op_log.txt")
def run_test_second(): def run_test_second():
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册