diff --git a/.ci/scripts/test_backend.sh b/.ci/scripts/test_backend.sh index a6dbeef9b12..d39ec3194f1 100755 --- a/.ci/scripts/test_backend.sh +++ b/.ci/scripts/test_backend.sh @@ -157,7 +157,15 @@ EXIT_CODE=0 # a step that size, taking the whole job down before pytest can report. The # reason for each failure is in its exception message and traceback, which are # unaffected. -PYTEST_ARGS=(-c /dev/null -n auto --show-capture=no) +# faulthandler_timeout is pytest's built-in stack dumper, so this adds no +# dependency and fails nothing: after 15 minutes in one test case it prints +# every thread's traceback and the case keeps running. A case that wedges +# otherwise leaves no trace at all - the job is cancelled at the job cap, the +# JSON report below is never written, and the artifact upload fails - which is +# how (coreml, models) spent a month at the 180 minute cap with no one able to +# say which model was stuck or where. Raise the value if a legitimate case ever +# runs this long. +PYTEST_ARGS=(-c /dev/null -o faulthandler_timeout=900 -n auto --show-capture=no) if [[ ${#PYTEST_RETRY_ARGS[@]} -gt 0 ]]; then PYTEST_ARGS+=("${PYTEST_RETRY_ARGS[@]}") fi diff --git a/backends/test/suite/models/test_torchvision.py b/backends/test/suite/models/test_torchvision.py index 58cf6a990d4..5fcd3d54287 100644 --- a/backends/test/suite/models/test_torchvision.py +++ b/backends/test/suite/models/test_torchvision.py @@ -40,11 +40,20 @@ def _test_cv_model( # Test a CV model that follows the standard conventions. inputs = (torch.randn(1, 3, 224, 224, dtype=dtype),) + # The declared minimum is 2, not 1. Until #23326 the exported program's + # range constraints were recomputed from the ShapeEnv after every pass, and + # the ShapeEnv raises a backed symbol's declared minimum of 0 or 1 to 2, so + # a declared min=1 never reached a backend: these models have always been + # lowered over height/width in [32, 256]. #23326 made ExecuTorch keep the + # declared range instead, which handed backends a lower bound of 16 for the + # first time and let a 16x16 input - degenerate for a network with a total + # stride of 32 - into backend shape reasoning. Declaring 2 states the bound + # that was always in force. dynamic_shapes = ( ( { - 2: Dim("height", min=1, max=16) * 16, - 3: Dim("width", min=1, max=16) * 16, + 2: Dim("height", min=2, max=16) * 16, + 3: Dim("width", min=2, max=16) * 16, }, ) if use_dynamic_shapes