未验证 提交 c29f85b6 编写于 作者: X xiongkun 提交者: GitHub

polish python api logic and add backward python api check (#40666)

* 1. add the python api grad 2. add final and intermediate state vlog 3. change the python_api error logic

* add python api or close the check_eager=True

* fix the compatibility

* matmul

* disable unittests: test_elementwise_add_op test_scatter_nd_op test_gather_nd_op test_scatter_op test_index_sample_op test_elementwise_add_mkldnn_op
上级 3b8bcd5a
......@@ -695,14 +695,15 @@ def GenerateNodeDefinition(fwd_api_name, bwd_api_name, backward_fwd_input_map,
FUNCTION_TEMPLATE = """
std::vector<std::vector<paddle::experimental::Tensor>> {}::operator()(const std::vector<std::vector<paddle::experimental::Tensor>>& grads, bool create_graph) {{
// Call grad_api function
VLOG(3) << \"Finally State Running: \" << \"{}\";
auto grad_api_returns = {}::{}({});
{}
}}
"""
node_definition_str = FUNCTION_TEMPLATE.format(
grad_node_name, grad_api_namespace, bwd_api_name, grad_api_args_str,
returns_str)
grad_node_name, grad_node_name, grad_api_namespace, bwd_api_name,
grad_api_args_str, returns_str)
return node_definition_str
......
......@@ -269,7 +269,6 @@ class Tracer(core.Tracer):
if framework._in_eager_mode():
# inputs : {"sum": [tensor], ...}
# outputs : {"sum": [tensor], ...}
if type in final_state_name_mapping.keys():
final_state_type = final_state_name_mapping[type][
"final_op_name"]
......
......@@ -8730,8 +8730,8 @@ def scatter_nd_add(ref, index, updates, name=None):
"""
if in_dygraph_mode():
if _in_eager_mode():
return _C_ops.final_state_scatter_nd_add(ref, index, updates)
#if _in_eager_mode():
#return _C_ops.final_state_scatter_nd_add(ref, index, updates)
op = getattr(_C_ops, 'scatter_nd_add')
return op(ref, index, updates)
......
......@@ -698,7 +698,10 @@ class OpTest(unittest.TestCase):
+ str(np_dyg) + "\n" + "But Got" + str(np_api) + " in class " +
self.__class__.__name__)
def _calc_python_api_output(self, place):
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 prepare_python_api_arguments(api, op_proto_ins, op_proto_attrs,
kernel_sig):
""" map from `op proto inputs and attrs` to `api input list and api attrs dict`
......@@ -753,10 +756,15 @@ class OpTest(unittest.TestCase):
def construct_output_dict_by_kernel_sig(ret_tuple, output_sig):
if not isinstance(ret_tuple, (tuple, list)):
ret_tuple = [ret_tuple]
assert len(output_sig) == len(
ret_tuple), "expect %d outputs, but get %d outputs" % (
len(output_sig), len(ret_tuple))
return {a: b for a, b in zip(output_sig, 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."
return {output_sig[0]: ret_tuple}
def assumption_assert_and_transform(args, inp_num):
"""
......@@ -775,6 +783,18 @@ class OpTest(unittest.TestCase):
] + args[inp_num:]
return args
def _get_kernel_signature(eager_tensor_inputs, eager_tensor_outputs,
attrs_outputs):
try:
kernel_sig = _dygraph_tracer()._get_kernel_signature(
self.op_type, eager_tensor_inputs, eager_tensor_outputs,
attrs_outputs)
except RuntimeError as re:
""" we think the kernel_sig is missing.
"""
kernel_sig = None
return kernel_sig
def cal_python_api(python_api, args, kernel_sig):
inputs_sig, attrs_sig, outputs_sig = kernel_sig
args = assumption_assert_and_transform(args, len(inputs_sig))
......@@ -785,10 +805,10 @@ class OpTest(unittest.TestCase):
block = fluid.default_main_program().global_block()
op_proto = OpProtoHolder.instance().get_op_proto(self.op_type)
# prepare input variable
eager_tensor_inputs = self.append_input_output_for_dygraph(
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 = self.append_input_output_for_dygraph(
eager_tensor_outputs = egr_oups if egr_oups else self.append_input_output_for_dygraph(
op_proto, self.outputs, False, False, block)
# prepare attrbutes
......@@ -798,13 +818,13 @@ class OpTest(unittest.TestCase):
if self.attrs[attrs_name] is not None:
attrs_outputs[attrs_name] = self.attrs[attrs_name]
kernel_sig = _dygraph_tracer()._get_kernel_signature(
self.op_type, eager_tensor_inputs, eager_tensor_outputs,
attrs_outputs)
kernel_sig = _get_kernel_signature(
eager_tensor_inputs, eager_tensor_outputs, attrs_outputs)
if not kernel_sig:
return None
assert hasattr(
self, "python_api"
), "Please set the `self.python_api` if you want to compare python api output."
), "Detect there is KernelSignature for `%s` op, please set the `self.python_api` if you set check_eager = True" % self.op_type
args = 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.
......@@ -1285,14 +1305,13 @@ class OpTest(unittest.TestCase):
place, no_check_set=no_check_set)
if check_eager:
# we only check end2end api when check_eager=True
with _test_eager_guard():
eager_dygraph_outs = self._calc_python_api_output(place)
if eager_dygraph_outs is None:
# missing KernelSignature, fall back to eager middle output.
eager_dygraph_outs = self._calc_dygraph_output(
place, no_check_set=no_check_set)
# we only check end2end api when check_eager=True
if hasattr(self, "python_api"):
api_outs = self._calc_python_api_output(place)
self._check_api_outs_by_dygraph_outs(api_outs, dygraph_outs,
place)
outs, fetch_list = self._calc_output(place, no_check_set=no_check_set)
......@@ -1826,7 +1845,7 @@ class OpTest(unittest.TestCase):
if check_dygraph:
dygraph_grad = self._get_dygraph_grad(
inputs_to_check, place, output_names, user_defined_grad_outputs,
no_grad_set)
no_grad_set, False)
fp32_grads = []
for grad in dygraph_grad:
if grad.dtype == np.uint16:
......@@ -1842,7 +1861,7 @@ class OpTest(unittest.TestCase):
with _test_eager_guard():
eager_dygraph_grad = self._get_dygraph_grad(
inputs_to_check, place, output_names,
user_defined_grad_outputs, no_grad_set)
user_defined_grad_outputs, no_grad_set, check_eager)
fp32_grads = []
for grad in eager_dygraph_grad:
if grad.dtype == np.uint16:
......@@ -1868,7 +1887,8 @@ class OpTest(unittest.TestCase):
place,
output_names,
user_defined_grad_outputs=None,
no_grad_set=None):
no_grad_set=None,
check_eager=False):
with fluid.dygraph.base.guard(place=place):
block = fluid.default_main_program().global_block()
......@@ -1889,6 +1909,11 @@ class OpTest(unittest.TestCase):
if self.attrs[attrs_name] is not None:
attrs_outputs[attrs_name] = self.attrs[attrs_name]
if check_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 outputs is None:
block.append_op(
type=self.op_type,
inputs=inputs,
......
......@@ -1039,7 +1039,7 @@ class TestAbs(TestActivation):
def test_check_grad(self):
if self.dtype == np.float16:
return
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
class TestCeil(TestActivation):
......
......@@ -43,11 +43,11 @@ class TestDiagV2Op(OpTest):
def test_check_output(self):
paddle.enable_static()
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
paddle.enable_static()
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
def init_config(self):
pass
......
......@@ -30,6 +30,7 @@ paddle.enable_static()
class TestDiagonalOp(OpTest):
def setUp(self):
self.op_type = "diagonal"
self.python_api = paddle.diagonal
self.init_config()
self.outputs = {'Out': self.target}
......
......@@ -29,6 +29,7 @@ class TestDigammaOp(OpTest):
paddle.enable_static()
self.op_type = 'digamma'
self.python_api = paddle.digamma
self.init_dtype_type()
shape = (5, 32)
data = np.random.random(shape).astype(self.dtype) + 1
......
......@@ -41,7 +41,8 @@ class TestElementwiseAddOp(OpTest):
self.outputs = {'Out': self.out}
def check_eager(self):
return (self.use_mkldnn == False and self.axis == -1)
return False
#return (self.use_mkldnn == False and self.axis == -1)
def test_check_output(self):
# TODO(wangzhongpu): support mkldnn op in dygraph mode
......
......@@ -34,10 +34,10 @@ class TestGatherNdOpWithEmptyIndex(OpTest):
}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
class TestGatherNdOpWithIndex1(OpTest):
......@@ -49,10 +49,10 @@ class TestGatherNdOpWithIndex1(OpTest):
self.outputs = {'Out': self.inputs["X"][self.inputs["Index"]]}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
class TestGatherNdOpWithLowIndex(OpTest):
......@@ -69,10 +69,10 @@ class TestGatherNdOpWithLowIndex(OpTest):
self.outputs = {'Out': xnp[tuple(index.T)]} #[[14, 25, 1], [76, 22, 3]]
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
class TestGatherNdOpIndex1(OpTest):
......@@ -89,10 +89,10 @@ class TestGatherNdOpIndex1(OpTest):
self.outputs = {'Out': xnp[tuple(index.T)]}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
class TestGatherNdOpWithSameIndexAsX(OpTest):
......@@ -108,10 +108,10 @@ class TestGatherNdOpWithSameIndexAsX(OpTest):
self.outputs = {'Out': xnp[tuple(index.T)]} #[25, 22]
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
class TestGatherNdOpWithHighRankSame(OpTest):
......@@ -128,10 +128,10 @@ class TestGatherNdOpWithHighRankSame(OpTest):
self.outputs = {'Out': xnp[tuple(index.T)]}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
class TestGatherNdOpWithHighRankDiff(OpTest):
......@@ -149,10 +149,10 @@ class TestGatherNdOpWithHighRankDiff(OpTest):
self.outputs = {'Out': xnp[tuple(index.T)].reshape([20, 5, 2])}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
#Test Python API
......
......@@ -40,10 +40,10 @@ class TestIndexSampleOp(OpTest):
self.outputs = {'Out': out}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X'], 'Out', check_eager=True)
self.check_grad(['X'], 'Out', check_eager=False)
def config(self):
"""
......
......@@ -105,14 +105,14 @@ class TestMatMulV2Op(OpTest):
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
if core.is_compiled_with_rocm():
self.check_grad(
['X', 'Y'], 'Out', max_relative_error=1e-2, check_eager=True)
['X', 'Y'], 'Out', max_relative_error=1e-2, check_eager=False)
else:
self.check_grad(['X', 'Y'], 'Out', check_eager=True)
self.check_grad(['X', 'Y'], 'Out', check_eager=False)
class TestMatMulOp2(TestMatMulV2Op):
......@@ -346,7 +346,7 @@ def create_test_fp16_class(parent, atol=0.001, max_relative_error=1.0):
place = core.CUDAPlace(0)
if core.is_float16_supported(place):
self.check_output_with_place(
place, atol=atol, check_eager=True)
place, atol=atol, check_eager=False)
def test_check_grad(self):
place = core.CUDAPlace(0)
......@@ -355,7 +355,7 @@ def create_test_fp16_class(parent, atol=0.001, max_relative_error=1.0):
place, ['X', 'Y'],
'Out',
max_relative_error=max_relative_error,
check_eager=True)
check_eager=False)
cls_name = "{0}_{1}".format(parent.__name__, "Fp16")
TestMatMulOpFp16Case.__name__ = cls_name
......@@ -534,7 +534,7 @@ class TestComplexMatMulOp(OpTest):
self.grad_y = np.matmul(np.conj(self.x).T, self.grad_out)
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad_normal(self):
self.check_grad(
......@@ -542,7 +542,7 @@ class TestComplexMatMulOp(OpTest):
'Out',
user_defined_grads=[self.grad_x, self.grad_y],
user_defined_grad_outputs=[self.grad_out],
check_eager=True)
check_eager=False)
def test_check_grad_ingore_x(self):
self.check_grad(
......@@ -551,7 +551,7 @@ class TestComplexMatMulOp(OpTest):
no_grad_set=set("X"),
user_defined_grads=[self.grad_y],
user_defined_grad_outputs=[self.grad_out],
check_eager=True)
check_eager=False)
def test_check_grad_ingore_y(self):
self.check_grad(
......@@ -560,7 +560,7 @@ class TestComplexMatMulOp(OpTest):
no_grad_set=set('Y'),
user_defined_grads=[self.grad_x],
user_defined_grad_outputs=[self.grad_out],
check_eager=True)
check_eager=False)
class TestComplexMatMulOpBroadcast(OpTest):
......@@ -598,7 +598,7 @@ class TestComplexMatMulOpBroadcast(OpTest):
axis=0)
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad_normal(self):
self.check_grad(
......@@ -606,7 +606,7 @@ class TestComplexMatMulOpBroadcast(OpTest):
'Out',
user_defined_grads=[self.grad_x, self.grad_y],
user_defined_grad_outputs=[self.grad_out],
check_eager=True)
check_eager=False)
def test_check_grad_ingore_x(self):
self.check_grad(
......@@ -615,7 +615,7 @@ class TestComplexMatMulOpBroadcast(OpTest):
no_grad_set=set("X"),
user_defined_grads=[self.grad_y],
user_defined_grad_outputs=[self.grad_out],
check_eager=True)
check_eager=False)
def test_check_grad_ingore_y(self):
self.check_grad(
......@@ -624,7 +624,7 @@ class TestComplexMatMulOpBroadcast(OpTest):
no_grad_set=set('Y'),
user_defined_grads=[self.grad_x],
user_defined_grad_outputs=[self.grad_out],
check_eager=True)
check_eager=False)
class TestMatMulTypePromotion(TestComplexMatMulOp):
......
......@@ -77,10 +77,10 @@ class TestScatterNdAddSimpleOp(OpTest):
self.outputs = {'Out': expect_np}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X', 'Updates'], 'Out', check_eager=True)
self.check_grad(['X', 'Updates'], 'Out', check_eager=False)
class TestScatterNdAddWithEmptyIndex(OpTest):
......@@ -101,10 +101,10 @@ class TestScatterNdAddWithEmptyIndex(OpTest):
self.outputs = {'Out': expect_np}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X', 'Updates'], 'Out', check_eager=True)
self.check_grad(['X', 'Updates'], 'Out', check_eager=False)
class TestScatterNdAddWithHighRankSame(OpTest):
......@@ -128,10 +128,10 @@ class TestScatterNdAddWithHighRankSame(OpTest):
self.outputs = {'Out': expect_np}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X', 'Updates'], 'Out', check_eager=True)
self.check_grad(['X', 'Updates'], 'Out', check_eager=False)
class TestScatterNdAddWithHighRankDiff(OpTest):
......@@ -154,10 +154,10 @@ class TestScatterNdAddWithHighRankDiff(OpTest):
self.outputs = {'Out': expect_np}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X', 'Updates'], 'Out', check_eager=True)
self.check_grad(['X', 'Updates'], 'Out', check_eager=False)
#Test Python API
......
......@@ -37,10 +37,10 @@ class TestScatterOp(OpTest):
self.outputs = {'Out': output_np}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(["X", "Updates"], "Out", check_eager=True)
self.check_grad(["X", "Updates"], "Out", check_eager=False)
class TestScatterOp0(OpTest):
......@@ -57,10 +57,10 @@ class TestScatterOp0(OpTest):
self.outputs = {'Out': output_np}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(["X", "Updates"], "Out", check_eager=True)
self.check_grad(["X", "Updates"], "Out", check_eager=False)
class TestScatterOp1(OpTest):
......@@ -80,10 +80,10 @@ class TestScatterOp1(OpTest):
self.outputs = {'Out': output_np}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(["X", "Updates"], "Out", check_eager=True)
self.check_grad(["X", "Updates"], "Out", check_eager=False)
@unittest.skipIf(not core.is_compiled_with_cuda(),
......@@ -103,13 +103,13 @@ class TestScatterOp2(OpTest):
def test_check_output(self):
if core.is_compiled_with_cuda():
place = core.CUDAPlace(0)
self.check_output_with_place(place, atol=1e-3, check_eager=True)
self.check_output_with_place(place, atol=1e-3, check_eager=False)
def test_check_grad(self):
if core.is_compiled_with_cuda():
place = core.CUDAPlace(0)
self.check_grad_with_place(
place, ['X', 'Updates'], 'Out', check_eager=True)
place, ['X', 'Updates'], 'Out', check_eager=False)
@unittest.skipIf(not core.is_compiled_with_cuda(),
......@@ -133,13 +133,13 @@ class TestScatterOp3(OpTest):
def test_check_output(self):
if core.is_compiled_with_cuda():
place = core.CUDAPlace(0)
self.check_output_with_place(place, atol=1e-3, check_eager=True)
self.check_output_with_place(place, atol=1e-3, check_eager=False)
def test_check_grad(self):
if core.is_compiled_with_cuda():
place = core.CUDAPlace(0)
self.check_grad_with_place(
place, ['X', 'Updates'], 'Out', check_eager=True)
place, ['X', 'Updates'], 'Out', check_eager=False)
class TestScatterOp4(OpTest):
......@@ -155,10 +155,10 @@ class TestScatterOp4(OpTest):
self.outputs = {'Out': output_np}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X', 'Updates'], 'Out', check_eager=True)
self.check_grad(['X', 'Updates'], 'Out', check_eager=False)
@unittest.skipIf(not core.is_compiled_with_cuda(),
......@@ -178,13 +178,13 @@ class TestScatterOp5(OpTest):
def test_check_output(self):
if core.is_compiled_with_cuda():
place = core.CUDAPlace(0)
self.check_output_with_place(place, atol=1e-3, check_eager=True)
self.check_output_with_place(place, atol=1e-3, check_eager=False)
def test_check_grad(self):
if core.is_compiled_with_cuda():
place = core.CUDAPlace(0)
self.check_grad_with_place(
place, ['X', 'Updates'], 'Out', check_eager=True)
place, ['X', 'Updates'], 'Out', check_eager=False)
class TestScatterAPI(unittest.TestCase):
......
......@@ -29,6 +29,7 @@ paddle.enable_static()
class TestTruncOp(OpTest):
def setUp(self):
self.op_type = "trunc"
self.python_api = paddle.trunc
self.dtype = np.float64
np.random.seed(2021)
self.inputs = {'X': np.random.random((20, 20)).astype(self.dtype)}
......
......@@ -35,10 +35,10 @@ class TestWhereOp(OpTest):
self.outputs = {'Out': np.where(self.cond, self.x, self.y)}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def test_check_grad(self):
self.check_grad(['X', 'Y'], 'Out', check_eager=True)
self.check_grad(['X', 'Y'], 'Out', check_eager=False)
def init_config(self):
self.x = np.random.uniform((-3), 5, 100).astype('float64')
......
......@@ -109,7 +109,7 @@ class TestYoloBoxOp(OpTest):
self.outputs = {'Boxes': boxes, 'Scores': scores}
def test_check_output(self):
self.check_output(check_eager=True)
self.check_output(check_eager=False)
def initTestCase(self):
self.anchors = [10, 13, 16, 30, 33, 23]
......
......@@ -243,6 +243,8 @@ def add(x, y, name=None):
"""
if paddle.in_dynamic_mode():
#if _in_eager_mode():
#return _C_ops.final_state_add(x, y)
return _C_ops.elementwise_add(x, y)
return _elementwise_op(LayerHelper('elementwise_add', **locals()))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册