未验证 提交 7e35ef3a 编写于 作者: W WeiXin 提交者: GitHub

[Cherry-Pick] Clear 'BasicEngine' when an exception occurs in the backward. (#32546) (#32615)

* clear 'BasicEngine' when an exception occurs in the backward. (#32546)

* clear 'BasicEngine' when an exception occurs in the backward.

* deal with conflict.

* deal with conflict.

* forward return any type. (#32661)
上级 4f06cd17
...@@ -471,12 +471,20 @@ void BasicEngine::Execute() { ...@@ -471,12 +471,20 @@ void BasicEngine::Execute() {
{ {
VLOG(3) << "Start to execute grad op " << cur_op.Type(); VLOG(3) << "Start to execute grad op " << cur_op.Type();
if (tmp_ins_ptr == nullptr) { try {
OpBase::Run(cur_op.InnerOp(), bwd_ins, tmp_outs, cur_op.Attrs(), if (tmp_ins_ptr == nullptr) {
cur_op.place()); OpBase::Run(cur_op.InnerOp(), bwd_ins, tmp_outs, cur_op.Attrs(),
} else { cur_op.place());
OpBase::Run(cur_op.InnerOp(), *tmp_ins_ptr, tmp_outs, cur_op.Attrs(), } else {
cur_op.place()); OpBase::Run(cur_op.InnerOp(), *tmp_ins_ptr, tmp_outs,
cur_op.Attrs(), cur_op.place());
}
} catch (platform::EnforceNotMet& exception) {
Clear();
throw std::move(exception);
} catch (std::exception& ex) {
Clear();
PADDLE_THROW(platform::errors::External("%s", ex.what()));
} }
} }
......
...@@ -115,12 +115,12 @@ py::object PyLayerApply(const platform::Place& place, const py::object& cls, ...@@ -115,12 +115,12 @@ py::object PyLayerApply(const platform::Place& place, const py::object& cls,
tuple_result[i].cast<std::shared_ptr<imperative::VarBase>>(); tuple_result[i].cast<std::shared_ptr<imperative::VarBase>>();
output_vars.push_back(temp_out); output_vars.push_back(temp_out);
} catch (py::cast_error&) { } catch (py::cast_error&) {
PADDLE_THROW(platform::errors::Unimplemented( // Only collect Tensor type in 'kwargs' and pass them to backward.
"The output of `PyLayer.forward` should be `Tensor`.")); // Ignore other types of input temporarily.
} }
} else { } else {
PADDLE_THROW(platform::errors::Unimplemented( // Only collect Tensor type in 'kwargs' and pass them to backward.
"The output of `PyLayer.forward` can not be `None`.")); // Ignore other types of input temporarily.
} }
} }
} else { } else {
...@@ -130,14 +130,18 @@ py::object PyLayerApply(const platform::Place& place, const py::object& cls, ...@@ -130,14 +130,18 @@ py::object PyLayerApply(const platform::Place& place, const py::object& cls,
result_forward.cast<std::shared_ptr<imperative::VarBase>>(); result_forward.cast<std::shared_ptr<imperative::VarBase>>();
output_vars.push_back(temp_out); output_vars.push_back(temp_out);
} catch (py::cast_error&) { } catch (py::cast_error&) {
PADDLE_THROW(platform::errors::Unimplemented( // Only collect Tensor type in 'kwargs' and pass them to backward.
"The output of `PyLayer.forward` should be `Tensor`.")); // Ignore other types of input temporarily.
} }
} else { } else {
PADDLE_THROW(platform::errors::Unimplemented( // Only collect Tensor type in 'kwargs' and pass them to backward.
"The output of `PyLayer.forward` can not be `None`.")); // Ignore other types of input temporarily.
} }
} }
if (output_vars.size() == 0) {
PADDLE_THROW(platform::errors::InvalidArgument(
"At least one output of `PyLayer.forward` is a `Tensor`."));
}
NameVarBaseMap outs = {{"Out", output_vars}}; NameVarBaseMap outs = {{"Out", output_vars}};
......
...@@ -86,6 +86,12 @@ void RunPyObject(py::object *py_object, ...@@ -86,6 +86,12 @@ void RunPyObject(py::object *py_object,
} }
} }
} else { } else {
if (1 != outs->size()) {
PADDLE_THROW(platform::errors::InvalidArgument(
"The number of outputs of `PyLayer.backward` should be %d, but "
"received 1.",
outs->size()));
}
if ((*outs)[0] != nullptr) { if ((*outs)[0] != nullptr) {
if (Py_None != py_result.ptr()) { if (Py_None != py_result.ptr()) {
try { try {
......
...@@ -30,7 +30,7 @@ class TestPyLayer(unittest.TestCase): ...@@ -30,7 +30,7 @@ class TestPyLayer(unittest.TestCase):
y1 = func1(x1) y1 = func1(x1)
y2 = func1(x2) y2 = func1(x2)
ctx.save_for_backward(y1, y2) ctx.save_for_backward(y1, y2)
return y1, y2 return y1, 1, y2, None
@staticmethod @staticmethod
def backward(ctx, dy1, dy2): def backward(ctx, dy1, dy2):
...@@ -44,7 +44,7 @@ class TestPyLayer(unittest.TestCase): ...@@ -44,7 +44,7 @@ class TestPyLayer(unittest.TestCase):
input1.stop_gradient = False input1.stop_gradient = False
input2.stop_gradient = False input2.stop_gradient = False
z = tanh.apply(input1, input1, paddle.tanh, paddle.square) z = tanh.apply(input1, input1, paddle.tanh, paddle.square)
z = z[0] + z[1] z = z[0] + z[2]
z.mean().backward() z.mean().backward()
z2 = paddle.tanh(input2) + paddle.tanh(input2) z2 = paddle.tanh(input2) + paddle.tanh(input2)
...@@ -61,7 +61,7 @@ class TestPyLayer(unittest.TestCase): ...@@ -61,7 +61,7 @@ class TestPyLayer(unittest.TestCase):
y1 = func1(x1) y1 = func1(x1)
y2 = func1(x2) y2 = func1(x2)
ctx.save_for_backward(y1, y2) ctx.save_for_backward(y1, y2)
return y1, y2 return 1, None, y1, y2, ''
@staticmethod @staticmethod
def backward(ctx, dy1, dy2): def backward(ctx, dy1, dy2):
...@@ -79,7 +79,7 @@ class TestPyLayer(unittest.TestCase): ...@@ -79,7 +79,7 @@ class TestPyLayer(unittest.TestCase):
input3.stop_gradient = True input3.stop_gradient = True
input4.stop_gradient = True input4.stop_gradient = True
z = tanh.apply(input1, input3, paddle.tanh, paddle.square) z = tanh.apply(input1, input3, paddle.tanh, paddle.square)
z = z[0] + z[1] z = z[2] + z[3]
z.mean().backward() z.mean().backward()
z2 = paddle.tanh(input2) + paddle.tanh(input4) z2 = paddle.tanh(input2) + paddle.tanh(input4)
...@@ -115,6 +115,27 @@ class TestPyLayer(unittest.TestCase): ...@@ -115,6 +115,27 @@ class TestPyLayer(unittest.TestCase):
self.assertTrue( self.assertTrue(
np.max(np.abs((input1.grad.numpy() - input2.grad.numpy()))) < 1e-10) np.max(np.abs((input1.grad.numpy() - input2.grad.numpy()))) < 1e-10)
def test_pylayer_num_output_match(self):
class tanh(PyLayer):
@staticmethod
def forward(
ctx,
x1,
x2, ):
return x1 + x2
@staticmethod
def backward(ctx, dy1):
return dy1 + 1
input1 = paddle.randn([2, 3]).astype("float64")
input2 = input1.detach().clone()
input1.stop_gradient = False
input2.stop_gradient = False
z = tanh.apply(input1, input2)
with self.assertRaises(ValueError):
z.mean().backward()
def test_pylayer_dtype(self): def test_pylayer_dtype(self):
class tanh(PyLayer): class tanh(PyLayer):
@staticmethod @staticmethod
...@@ -150,21 +171,21 @@ class TestPyLayer(unittest.TestCase): ...@@ -150,21 +171,21 @@ class TestPyLayer(unittest.TestCase):
return args return args
input1 = paddle.randn([2, 3]).astype("float64") input1 = paddle.randn([2, 3]).astype("float64")
with self.assertRaises(NotImplementedError): with self.assertRaises(ValueError):
z = Layer_None1.apply(input1) z = Layer_None1.apply(input1)
class Layer_None2(PyLayer): class Layer_None2(PyLayer):
@staticmethod @staticmethod
def forward(ctx, *args): def forward(ctx, *args):
return [None, None] return [None, args[0]]
@staticmethod @staticmethod
def backward(ctx, *args): def backward(ctx, *args):
return args return args
input1 = paddle.randn([2, 3]).astype("float64") input1 = paddle.randn([2, 3]).astype("float64")
with self.assertRaises(NotImplementedError): # return None
z = Layer_None2.apply(input1) z = Layer_None2.apply(input1)
class Layer_one1(PyLayer): class Layer_one1(PyLayer):
@staticmethod @staticmethod
...@@ -176,21 +197,22 @@ class TestPyLayer(unittest.TestCase): ...@@ -176,21 +197,22 @@ class TestPyLayer(unittest.TestCase):
return args return args
input1 = paddle.randn([2, 3]).astype("float64") input1 = paddle.randn([2, 3]).astype("float64")
with self.assertRaises(NotImplementedError): # At least one output of `PyLayer.backward` is a `Tensor`
with self.assertRaises(ValueError):
z = Layer_one1.apply(input1) z = Layer_one1.apply(input1)
class Layer_one2(PyLayer): class Layer_one2(PyLayer):
@staticmethod @staticmethod
def forward(ctx, *args): def forward(ctx, *args):
return [1, 2] return [1, 2, args[0]]
@staticmethod @staticmethod
def backward(ctx, *args): def backward(ctx, *args):
return args return args
input1 = paddle.randn([2, 3]).astype("float64") input1 = paddle.randn([2, 3]).astype("float64")
with self.assertRaises(NotImplementedError): # return int
z = Layer_one2.apply(input1) z = Layer_one2.apply(input1)
class Layer_no_fw(PyLayer): class Layer_no_fw(PyLayer):
@staticmethod @staticmethod
...@@ -234,8 +256,7 @@ class TestPyLayer(unittest.TestCase): ...@@ -234,8 +256,7 @@ class TestPyLayer(unittest.TestCase):
z = Layer_bk_none1.apply(input2) z = Layer_bk_none1.apply(input2)
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
with paddle.fluid.dygraph.guard(): z.sum().backward()
z.sum().backward()
class Layer_bk_none2(PyLayer): class Layer_bk_none2(PyLayer):
@staticmethod @staticmethod
...@@ -249,9 +270,9 @@ class TestPyLayer(unittest.TestCase): ...@@ -249,9 +270,9 @@ class TestPyLayer(unittest.TestCase):
input1 = paddle.randn([2, 3]).astype("float64") input1 = paddle.randn([2, 3]).astype("float64")
input1.stop_gradient = False input1.stop_gradient = False
z = Layer_bk_none2.apply(input1, input1) z = Layer_bk_none2.apply(input1, input1)
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
with paddle.fluid.dygraph.guard(): z.mean().backward()
z.mean().backward()
class Layer_bk_one1(PyLayer): class Layer_bk_one1(PyLayer):
@staticmethod @staticmethod
...@@ -265,9 +286,9 @@ class TestPyLayer(unittest.TestCase): ...@@ -265,9 +286,9 @@ class TestPyLayer(unittest.TestCase):
input1 = paddle.randn([2, 3]).astype("float64") input1 = paddle.randn([2, 3]).astype("float64")
input1.stop_gradient = False input1.stop_gradient = False
z = Layer_bk_one1.apply(input1) z = Layer_bk_one1.apply(input1)
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
with paddle.fluid.dygraph.guard(): z.mean().backward()
z.mean().backward()
class Layer_bk_one2(PyLayer): class Layer_bk_one2(PyLayer):
@staticmethod @staticmethod
...@@ -280,11 +301,11 @@ class TestPyLayer(unittest.TestCase): ...@@ -280,11 +301,11 @@ class TestPyLayer(unittest.TestCase):
input1 = paddle.randn([2, 3]).astype("float64") input1 = paddle.randn([2, 3]).astype("float64")
input1.stop_gradient = False input1.stop_gradient = False
y = Layer_bk_one2.apply(input1, input1) y = Layer_bk_one2.apply(input1, input1)
z = y[0] + y[1] z = y[0] + y[1]
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
with paddle.fluid.dygraph.guard(): z.mean().backward()
z.mean().backward()
class Layer_no_bk(PyLayer): class Layer_no_bk(PyLayer):
@staticmethod @staticmethod
...@@ -295,10 +316,9 @@ class TestPyLayer(unittest.TestCase): ...@@ -295,10 +316,9 @@ class TestPyLayer(unittest.TestCase):
input1.stop_gradient = False input1.stop_gradient = False
z = Layer_no_bk.apply(input1) z = Layer_no_bk.apply(input1)
with self.assertRaises(NotImplementedError): with self.assertRaises(OSError):
with paddle.fluid.dygraph.guard(): z = z[0] + z[1]
z = z[0] + z[1] z.mean().backward()
z.mean().backward()
class Layer_bk_match(PyLayer): class Layer_bk_match(PyLayer):
@staticmethod @staticmethod
...@@ -313,9 +333,8 @@ class TestPyLayer(unittest.TestCase): ...@@ -313,9 +333,8 @@ class TestPyLayer(unittest.TestCase):
input1.stop_gradient = False input1.stop_gradient = False
z = Layer_bk_match.apply(input1) z = Layer_bk_match.apply(input1)
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
with paddle.fluid.dygraph.guard(): z = z[0] + z[1]
z = z[0] + z[1] z.mean().backward()
z.mean().backward()
def test_pylayer_bk_return_none(self): def test_pylayer_bk_return_none(self):
class Layer_bk_none1(PyLayer): class Layer_bk_none1(PyLayer):
...@@ -334,8 +353,7 @@ class TestPyLayer(unittest.TestCase): ...@@ -334,8 +353,7 @@ class TestPyLayer(unittest.TestCase):
z = Layer_bk_none1.apply(input1, input2) z = Layer_bk_none1.apply(input1, input2)
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
with paddle.fluid.dygraph.guard(): z.mean().backward()
z.mean().backward()
class Layer_bk_none2(PyLayer): class Layer_bk_none2(PyLayer):
@staticmethod @staticmethod
...@@ -353,8 +371,7 @@ class TestPyLayer(unittest.TestCase): ...@@ -353,8 +371,7 @@ class TestPyLayer(unittest.TestCase):
z = Layer_bk_none2.apply(input1, input2) z = Layer_bk_none2.apply(input1, input2)
z = z[0] + z[1] z = z[0] + z[1]
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
with paddle.fluid.dygraph.guard(): z.mean().backward()
z.mean().backward()
def test_pylayer_inplace(self): def test_pylayer_inplace(self):
class cus_tanh(PyLayer): class cus_tanh(PyLayer):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册