mirror of
https://github.com/pytorch/pytorch.git
synced 2025-10-20 21:14:14 +08:00
[BE][tests] show local variables on failure in tests (#131151)
------ As per the title, add argument `--locals` for `unittest` and `--showlocals --tb=long` for `pytest` in CI. Some failures cannot be reproduced on the local machine but exist on cloud CI. This change allows us to investigate the test failure more easily. Example output: https://github.com/pytorch/pytorch/actions/runs/9961546996/job/27523888353?pr=130710#step:20:3361 ```text /opt/conda/envs/py_3.8/lib/python3.8/site-packages/sympy/core/function.py:307: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cls = FloorDiv, base = -1.00000000000000, divisor = -1.00000000000000 @classmethod def eval(cls, base, divisor): # python test/test_dynamic_shapes.py -k TestDimConstraints.test_dim_constraints_solve_full # Assert triggered by inequality solver # assert base.is_integer, base # assert divisor.is_integer, divisor # We don't provide the same error message as in Python because SymPy # makes it difficult to check the types. if divisor.is_zero: raise ZeroDivisionError("division by zero") if base in (int_oo, -int_oo, sympy.oo, -sympy.oo) and divisor in ( int_oo, -int_oo, sympy.oo, -sympy.oo, ): return sympy.nan if base is sympy.nan or divisor is sympy.nan: return sympy.nan if base.is_zero: return sympy.S.Zero if base.is_integer and divisor == 1: return base if base.is_integer and divisor == -1: return sympy.Mul(base, -1) if ( isinstance(base, sympy.Number) and isinstance(divisor, sympy.Number) and ( base in (int_oo, -int_oo, sympy.oo, -sympy.oo) or divisor in (int_oo, -int_oo, sympy.oo, -sympy.oo) ) ): r = float(base) / float(divisor) if r == math.inf: return int_oo elif r == -math.inf: return -int_oo elif math.isnan(r): return sympy.nan else: return sympy.Integer(math.floor(r)) if isinstance(base, sympy.Integer) and isinstance(divisor, sympy.Integer): return sympy.Integer(int(base) // int(divisor)) if isinstance(base, FloorDiv): return FloorDiv(base.args[0], base.args[1] * divisor) # Expands (x + y) // b into x // b + y // b. # This only works if floor is an identity, i.e. x / b is an integer. for term in sympy.Add.make_args(base): quotient = term / divisor if quotient.is_integer and isinstance(divisor, sympy.Integer): # NB: this is correct even if the divisor is not an integer, but it # creates rational expressions that cause problems with dynamic # shapes. return FloorDiv(base - term, divisor) + quotient try: gcd = sympy.gcd(base, divisor) if gcd != 1: > return FloorDiv( sympy.simplify(base / gcd), sympy.simplify(divisor / gcd) ) base = -1.00000000000000 cls = FloorDiv divisor = -1.00000000000000 gcd = 1.00000000000000 quotient = 1.00000000000000 term = -1.00000000000000 /opt/conda/envs/py_3.8/lib/python3.8/site-packages/torch/utils/_sympy/functions.py:159: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ args = (FloorDiv, -1.00000000000000, -1.00000000000000), kwargs = {} @wraps(func) def wrapper(*args, **kwargs): try: > retval = cfunc(*args, **kwargs) E RecursionError: maximum recursion depth exceeded in comparison E E To execute this test, run the following from the base repo dir: E python test/test_sympy_utils.py -k TestValueRanges.test_binary_ref_fn_floordiv_dtype_float E E This message can be suppressed by setting PYTORCH_PRINT_REPRO_ON_FAILURE=0 args = (FloorDiv, -1.00000000000000, -1.00000000000000) cfunc = <functools._lru_cache_wrapper object at 0x7fc5303173a0> func = <function Function.__new__ at 0x7fc530317280> kwargs = {} ``` Pull Request resolved: https://github.com/pytorch/pytorch/pull/131151 Approved by: https://github.com/ezyang
This commit is contained in:
committed by
PyTorch MergeBot
parent
ab912b7fef
commit
4694ee1ad2
@ -4,6 +4,8 @@ addopts =
|
||||
-rEfX
|
||||
# Make tracebacks shorter
|
||||
--tb=native
|
||||
# Color the output
|
||||
--color=yes
|
||||
# capture only Python print and C++ py::print, but not C output (low-level Python errors)
|
||||
--capture=sys
|
||||
# don't suppress warnings, but don't shove them all to the end either
|
||||
|
@ -430,7 +430,14 @@ def run_test(
|
||||
)
|
||||
)
|
||||
unittest_args.extend(test_module.get_pytest_args())
|
||||
unittest_args = [arg if arg != "-f" else "-x" for arg in unittest_args]
|
||||
replacement = {"-f": "-x"}
|
||||
unittest_args = [replacement.get(arg, arg) for arg in unittest_args]
|
||||
|
||||
if options.showlocals:
|
||||
if options.pytest:
|
||||
unittest_args.extend(["--showlocals", "--tb=long", "--color=yes"])
|
||||
else:
|
||||
unittest_args.append("--locals")
|
||||
|
||||
# NB: These features are not available for C++ tests, but there is little incentive
|
||||
# to implement it because we have never seen a flaky C++ test before.
|
||||
@ -1118,6 +1125,21 @@ def parse_args():
|
||||
default=0,
|
||||
help="Print verbose information and test-by-test results",
|
||||
)
|
||||
if sys.version_info >= (3, 9):
|
||||
parser.add_argument(
|
||||
"--showlocals",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=False,
|
||||
help="Show local variables in tracebacks (default: True)",
|
||||
)
|
||||
else:
|
||||
parser.add_argument(
|
||||
"--showlocals",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Show local variables in tracebacks (default: True)",
|
||||
)
|
||||
parser.add_argument("--no-showlocals", dest="showlocals", action="store_false")
|
||||
parser.add_argument("--jit", "--jit", action="store_true", help="run all jit tests")
|
||||
parser.add_argument(
|
||||
"--distributed-tests",
|
||||
|
@ -859,6 +859,11 @@ parser.add_argument('--import-slow-tests', type=str, nargs='?', const=DEFAULT_SL
|
||||
parser.add_argument('--import-disabled-tests', type=str, nargs='?', const=DEFAULT_DISABLED_TESTS_FILE)
|
||||
parser.add_argument('--rerun-disabled-tests', action='store_true')
|
||||
parser.add_argument('--pytest-single-test', type=str, nargs=1)
|
||||
if sys.version_info >= (3, 9):
|
||||
parser.add_argument('--showlocals', action=argparse.BooleanOptionalAction, default=False)
|
||||
else:
|
||||
parser.add_argument('--showlocals', action='store_true', default=False)
|
||||
parser.add_argument('--no-showlocals', dest='showlocals', action='store_false')
|
||||
|
||||
# Only run when -h or --help flag is active to display both unittest and parser help messages.
|
||||
def run_unittest_help(argv):
|
||||
@ -894,6 +899,7 @@ TEST_IN_SUBPROCESS = args.subprocess
|
||||
TEST_SAVE_XML = args.save_xml
|
||||
REPEAT_COUNT = args.repeat
|
||||
SEED = args.seed
|
||||
SHOWLOCALS = args.showlocals
|
||||
if not getattr(expecttest, "ACCEPT", False):
|
||||
expecttest.ACCEPT = args.accept
|
||||
UNITTEST_ARGS = [sys.argv[0]] + remaining
|
||||
@ -1131,6 +1137,13 @@ def run_tests(argv=UNITTEST_ARGS):
|
||||
if not lint_test_case_extension(suite):
|
||||
sys.exit(1)
|
||||
|
||||
if SHOWLOCALS:
|
||||
argv = [
|
||||
argv[0],
|
||||
*(["--showlocals", "--tb=long", "--color=yes"] if USE_PYTEST else ["--locals"]),
|
||||
*argv[1:],
|
||||
]
|
||||
|
||||
if TEST_IN_SUBPROCESS:
|
||||
other_args = []
|
||||
if DISABLED_TESTS_FILE:
|
||||
@ -4914,7 +4927,6 @@ dtype_abbrs = {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
def get_cycles_per_ms() -> float:
|
||||
"""Measure and return approximate number of cycles per millisecond for torch.cuda._sleep
|
||||
|
Reference in New Issue
Block a user