diff --git a/python/paddle/fluid/tests/unittests/op_test.py b/python/paddle/fluid/tests/unittests/op_test.py index 3117aeb08905cfa7cb19f8948369abe98d839758..8bb1317b032f8039c81a7262725d332bf5811cbf 100644 --- a/python/paddle/fluid/tests/unittests/op_test.py +++ b/python/paddle/fluid/tests/unittests/op_test.py @@ -520,6 +520,10 @@ class OpTest(unittest.TestCase): """ # 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. if inplace_atol is not None: self.assertTrue( np.allclose( @@ -971,10 +975,17 @@ class OpTest(unittest.TestCase): "Output (" + out_name + ") has different lod at " + 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: 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. # No effect on original OpTest self.check_inplace_output_with_place( diff --git a/python/paddle/fluid/tests/unittests/test_group_norm_op.py b/python/paddle/fluid/tests/unittests/test_group_norm_op.py index 1d073c82b406087831d8eb7cf5904ccde50c725f..6f3961fc03ebd41566408712697633671d9c01aa 100644 --- a/python/paddle/fluid/tests/unittests/test_group_norm_op.py +++ b/python/paddle/fluid/tests/unittests/test_group_norm_op.py @@ -68,15 +68,22 @@ class TestGroupNormOp(OpTest): self.attrs['data_layout'] = self.data_format def test_check_output(self): - atol = 1e-4 - inplace_atol = 1e-4 + atol = 0.0 + inplace_atol = 0.0 place = core.CPUPlace() - # add inplace_atol bacause group_norm doesn't ensure computational consistency - self.check_output_with_place( - place, atol=atol, inplace_atol=inplace_atol) + + self.check_output_with_place(place, atol=atol) if core.is_compiled_with_cuda(): 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( place, atol=atol, inplace_atol=inplace_atol)