提交 c50ebeac 编写于 作者: L Leo Chen 提交者: Tao Luo

add comments of inplace_atol (#21819)

上级 8b7c50f4
...@@ -520,6 +520,10 @@ class OpTest(unittest.TestCase): ...@@ -520,6 +520,10 @@ class OpTest(unittest.TestCase):
""" """
# compare expect_outs and actual_outs # compare expect_outs and actual_outs
for i, name in enumerate(fetch_list): 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.
if inplace_atol is not None: if inplace_atol is not None:
self.assertTrue( self.assertTrue(
np.allclose( np.allclose(
...@@ -971,10 +975,17 @@ class OpTest(unittest.TestCase): ...@@ -971,10 +975,17 @@ class OpTest(unittest.TestCase):
"Output (" + out_name + ") has different lod at " + "Output (" + out_name + ") has different lod at " +
str(place) + " in dygraph mode") str(place) + " in dygraph mode")
# inplace_atol only used when op doesn't ensure computational consistency # 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: if inplace_atol is not None:
warnings.warn( warnings.warn(
"By default, inplace_atol should not be set, please check it") "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. # Check inplace for given op, its grad op, its grad_grad op, etc.
# No effect on original OpTest # No effect on original OpTest
self.check_inplace_output_with_place( self.check_inplace_output_with_place(
......
...@@ -68,15 +68,22 @@ class TestGroupNormOp(OpTest): ...@@ -68,15 +68,22 @@ class TestGroupNormOp(OpTest):
self.attrs['data_layout'] = self.data_format self.attrs['data_layout'] = self.data_format
def test_check_output(self): def test_check_output(self):
atol = 1e-4 atol = 0.0
inplace_atol = 1e-4 inplace_atol = 0.0
place = core.CPUPlace() place = core.CPUPlace()
# add inplace_atol bacause group_norm doesn't ensure computational consistency
self.check_output_with_place( self.check_output_with_place(place, atol=atol)
place, atol=atol, inplace_atol=inplace_atol)
if core.is_compiled_with_cuda(): if core.is_compiled_with_cuda():
place = core.CUDAPlace(0) place = core.CUDAPlace(0)
# 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.
# Set to inplace_atol to 0, which means the absolute error is 0, and the
# relative error is 1e-05 in numpy.allclose by default.
# Reference: https://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html
self.check_output_with_place( self.check_output_with_place(
place, atol=atol, inplace_atol=inplace_atol) place, atol=atol, inplace_atol=inplace_atol)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册