Repository navigation
ci: warm the GPU uv cache on a CPU runner before GPU jobs - #798
Conversation
When the per-CUDA uv cache entry is missing (first run after a pyproject.toml change, or after eviction), every GPU job downloads ~280 packages. On slow nights that has pushed setup past the 60-minute GPU job timeout while holding an A100. Add a warm-uv-cache job (one per CUDA extra) on a CPU runner with a 120-minute timeout. It computes the same setup-uv cache key as the GPU jobs, checks for an existing entry through the API, and on a miss installs the wheel for every smoke-test Python version and saves the cache. GPU jobs wait for it but still run if it fails. Signed-off-by: Yunfeng Zhang <yunzhang@nvidia.com>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Warm CUDA dependency caches .github/workflows/gpu-tests.yml |
A CPU job checks for matching cu129 and cu130 caches. On a cache miss, it builds the wheel and installs GPU test dependencies for Python 3.11–3.14. |
Wire cache warming to GPU jobs .github/workflows/gpu-tests.yml |
The smoke-test and E2E jobs now depend on cache warming. The smoke-test job retains its existing always() condition. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Other
Possibly related PRs
- NVIDIA-NeMo/Safe-Synthesizer#795: Changes the
setup-uvcache key to separate entries forcu129andcu130, which this workflow warms.
Suggested labels: perf, chore
Suggested reviewers: binaryaaron
Merge Risk: 
Minimal · up to d833f
-
GPU jobs wait for cache warming but can proceed if it fails. No merge-blocking issue was identified.
Pre-merge checks: 
4
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
[Low impact] The PR appears safe to merge; no blocking issue was found. SummaryAdds a CPU job that warms the GPU download cache separately for each CUDA extra.
Acknowledged scope:
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Summary
Follow-up to #795. GPU jobs restore one uv cache entry per CUDA extra, keyed on a hash of
pyproject.tomland.python-version. When that entry is missing (the first nightly after anypyproject.tomlchange, about weekly, or after eviction), every GPU job downloads ~280 packages itself. On slow nights that has run past the 60-minute smoke job timeout while holding an A100: nightly 40437182386, the first after #795 merged, lost 4 smoke jobs this way (one cu129 job spent 44m 44s downloading; three cu130 jobs never finished).This PR adds a
warm-uv-cachejob (one per CUDA extra) onlinux-amd64-cpu4with a 120-minute timeout. The GPU smoke and e2e jobs nowneeds:it and keep their 60-minute limit.How it works:
setup-uvwith the same key-affecting inputs assetup-gpu-test-env(enable-cache,cache-suffix,cache-dependency-glob, nopython-version), with restore and save off, to get the exact cache key.setup-uvagain with saving on, builds the wheel, and runsinstall_nss.shfor Python 3.11-3.14 so every version's torch wheels land in one entry. Thesetup-uvpost step saves it.Details:
setup-uvstep so a hit never uploads an empty cache; on a branch that would shadowmain's entry..mise.toml(0.13.4), which is what the GPU install actually runs (mise shims precede thesetup-uvbinary onPATH). The uv version is not part of the cache key.VM-Images version: 78c50ae) and cache path (/home/runner/.cache/uv), so keys and cache versions match.always()) and fill the cache themselves as before.PYTHON_VERSIONSduplicates the smoke matrix; a comment marks it to keep in sync.Human review
Select exactly one. The default is no human review; uncheck it when choosing another level.
Verification performed: manual GPU smoke run 40518808190 on this branch. Both warming jobs computed keys identical to
main's-cu129/-cu130entries, found them, and exited in 17 s; all 8 GPU smoke jobs then hit the cache and passed. actionlint reports only the self-hosted runner labels it doesn't know.Not yet exercised: the cache-miss path (install on a CPU runner, save, GPU jobs restoring that entry). Testing it on a branch creates ~12 GB of branch-scoped entries that would evict
main's, so it is left to the first nightly after the nextpyproject.tomlchange. If it misbehaves, GPU jobs fall back to filling the cache as they do today.Pre-Review Checklist
Ensure that the following pass:
mise run formatleaves only intended formatting changes.mise run check ::: testpasses locally.mise run test:e2epasses locallymise run test:ci-containerpasses locally (recommended)/syncon this PR to trigger a run (auto-triggers on ready-for-review)Pre-Merge Checklist
Other Notes
Summary by CodeRabbit