Skip to content

fix(tests): download the shared torchvision checkpoints before pytest forks - #4587

Open
shoumikhin wants to merge 2 commits into
pytorch:mainfrom
shoumikhin:fix/ts-hub-weight-race
Open

fix(tests): download the shared torchvision checkpoints before pytest forks#4587
shoumikhin wants to merge 2 commits into
pytorch:mainfrom
shoumikhin:fix/ts-hub-weight-race

Conversation

@shoumikhin

Copy link
Copy Markdown
Contributor

Problem

ts-api on Windows is red on most main runs, one or two configs at a time, and the configs move around:

FAILED api/test_operator_fallback.py::TestFallbackModels::test_fallback_mobilenet_v2
_pickle.UnpicklingError: pickle data was truncated

Other runs show invalid load key, '\x00' for the same test. Linux never fails this way.

Cause

addopts in pyproject.toml carries --dist=loadfile, so pytest gives each test file its own xdist worker. api/test_operator_fallback.py and api/test_module_fallback.py both open with models.mobilenet_v2(pretrained=True), so two workers download the same checkpoint at the same time.

torch.hub.download_url_to_file writes to a temporary file and finishes with shutil.move. shutil.move calls os.rename and falls back to a plain copy when that raises. On Linux os.rename over an existing file succeeds and is atomic. On Windows it raises FileExistsError, so the fallback copy rewrites the file in place while the other worker is reading it, and torch.load sees a truncated pickle. That is why the failure is Windows only and why it lands on a different config each run.

resnet18 is in the same position: three files in api/, two in models/, two in integrations/.

Fix

The three tests/py/ts suites already run tests/modules/hub.py as a setup step to put what they need on disk before pytest starts. It does not cover the torchvision checkpoints, so fetch those there as well. One process, no concurrent writers, and the workers only ever read. Checkpoints that only one file uses cannot race, so they are left alone. A download failure here is reported and ignored, because warming the cache is an optimization and the tests still fetch what they need.

Testing

The prefetch runs only in the hub setup step, which the CI logs show already executing for ts-api. Windows CI is the place this can be confirmed; the failure needs two workers racing, which does not reproduce on Linux.

… forks

ts-api is red on Windows on most main runs:

  FAILED api/test_operator_fallback.py::TestFallbackModels::test_fallback_mobilenet_v2
  _pickle.UnpicklingError: pickle data was truncated

pytest runs one test file per xdist worker (addopts carries --dist=loadfile),
and api/test_operator_fallback.py and api/test_module_fallback.py both open with
models.mobilenet_v2(pretrained=True). Two workers therefore download the same
checkpoint at the same time. torch.hub finishes a download with shutil.move,
which calls os.rename and falls back to a plain copy when that raises. On Linux
os.rename over an existing file succeeds and is atomic; on Windows it raises
FileExistsError, so the second worker copies over the file the first one is
reading and torch.load sees a truncated pickle. That is why this only ever
fails on Windows, and why the config that fails moves around between runs.
resnet18 is in the same position: three files in api, two in models and two in
integrations.

The ts suites already run tests/modules/hub.py as a setup step to put what they
need on disk before pytest starts. It just does not cover the torchvision
checkpoints, so fetch those there too. One process, no concurrent writers, and
the workers only ever read. Checkpoints only one file uses cannot race, so they
are left alone.
@meta-cla meta-cla Bot added the cla signed label Aug 26, 2026
@github-actions github-actions Bot added the component: tests Issues re: Tests label Aug 26, 2026
@github-actions
github-actions Bot requested a review from lanluo-nvidia August 26, 2026 03:09
The repository lint job runs `black --check .` across the whole tree, so any
file that does not match the formatter fails CI for every open pull request,
not only the one that touched it. `tests/py/dynamo/conversion/test_cumsum_aten.py`
is currently not black-conformant on main, which turns the Python Linting check
red here.

Reformat that one file with black. This is a formatting-only change: two
statements that fit on a single line are un-wrapped. No test logic changes.

Verified by running `black --check .` on the full tree: all files pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant