-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[None][test] Add opt-in background prefetch of test MPI sessions and model page cache #15908
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
5628261
[None][test] Add opt-in background prefetch of test MPI sessions and …
sunnyqgg 21bff28
[None][test] Add prefetched_mpi_session fixture so tests can consume …
sunnyqgg 82f6ea0
[None][test] Enable prefetch by default and add zero-test-change shad…
sunnyqgg 5be73d7
[None][test] Include single-GPU pools in shadow prefetch
sunnyqgg 699bc77
[None][test] Fix two issues found by running unmodified tests under s…
sunnyqgg e421332
[None][test] Wire prefetch repo-wide as a pytest plugin with lazy, de…
sunnyqgg a9b509a
[None][test] Fix three prefetch handover bugs found in pre-merge CI
sunnyqgg 356d5ab
[None][test] Harden session prefetcher per review findings
sunnyqgg 6c774b4
[None][test] Simplify prefetcher: single shadow mechanism, O(1) warm …
sunnyqgg b80974c
[None][test] Auto-discover the next test's model for weight warming
sunnyqgg 7806459
[None][test] Align warming with the weight loader and harden its trig…
sunnyqgg 1716ec0
[None][test] Final polish for review: hook-level fail-open and docs
sunnyqgg e0aef12
[None][test] Refuse handover into a mostly-used GPU (sync fallback)
sunnyqgg fcc7a04
[None][test] Drop the tests/README.md note (plugin docs live in the m…
sunnyqgg 6903da2
[None][test] Add prefetch session summary and warm the heavy Nemotron…
sunnyqgg ec1b9c9
[None][test] Yield the MPI pool seams to session reuse when it is active
sunnyqgg cc4b315
[None][test] Consolidate session_reuse/session_prefetcher shared helpers
sunnyqgg 7f7745a
[None][fix] MpiPoolSession: opt-in wait for worker exit at shutdown
sunnyqgg 9465429
[None][test] Retire the NVML settle barrier; flag test-owned pools in…
sunnyqgg 46d59bb
[None][test] Reuse the library's worker identities in session_reuse
sunnyqgg f2f1c50
[None][test] Reap in-flight retires before an instant cached-pool han…
sunnyqgg f1a8d82
[None][test] Vend prefetched shadow pools to session reuse's cache mi…
sunnyqgg 68a0726
[None][test] take(): do not stall behind an in-flight build of anothe…
sunnyqgg a4e0bb1
[None][test] Discover the model from parametrized model_folder-style …
sunnyqgg 98532ff
[None][test] Wire the prefetcher into the tests/ fallback conftest
sunnyqgg 2c36d7a
[None][test] Dispatch prefetcher hooks explicitly from nested conftests
sunnyqgg a6e708a
[None][fix] Fail closed when wait_shutdown identity collection is inc…
sunnyqgg fab760a
[None][test] Canary rollout: enable prefetch only on two stage groups
sunnyqgg c691956
[None][test] Make the session-reuse pool seam isinstance-transparent
sunnyqgg 54f4ae1
[None][test] Share the isinstance-transparent seam shim with the pref…
sunnyqgg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,49 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| """Fallback wiring of the session-reuse plugin for test dirs WITHOUT an ini. | ||
|
|
||
| tests/unittest and tests/integration/defs load the plugin through the ``-p`` | ||
| option in their own pytest.ini; their rootdir sits below this file, so this | ||
| conftest is never collected there (no double registration). Any other | ||
| directory under tests/ (current or future) resolves its rootdir at the repo | ||
| root and picks the hooks up from here, so automatic MPI session reuse covers | ||
| every test under tests/. | ||
| """Fallback wiring of the session-reuse and session-prefetch plugins. | ||
|
|
||
| tests/unittest and tests/integration/defs load the plugins through their own | ||
| pytest.ini / conftest; their rootdir sits below this file, so this conftest | ||
| is never collected there (no double registration). Any other directory under | ||
| tests/ (current or future) picks the hooks up from here, so MPI session | ||
| reuse and prefetch cover every test under tests/. | ||
|
|
||
| Both plugins define same-named hooks, and ``pytest_plugins`` is only allowed | ||
| in a rootdir conftest (this file is not one when pytest runs from the repo | ||
| root) — so dispatch to both modules explicitly instead of importing their | ||
| hook functions into this namespace (the second import would silently shadow | ||
| the first). | ||
| """ | ||
|
|
||
| import os | ||
| import sys | ||
|
|
||
| sys.path.insert(0, os.path.dirname(__file__)) # make test_common importable | ||
|
|
||
| from test_common.session_reuse_hooks import ( # noqa: E402,F401 | ||
| pytest_configure, | ||
| pytest_runtest_setup, | ||
| pytest_sessionfinish, | ||
| ) | ||
| from test_common import session_prefetcher_hooks as _prefetch # noqa: E402 | ||
| from test_common import session_reuse_hooks as _reuse # noqa: E402 | ||
|
|
||
|
|
||
| def pytest_configure(config): | ||
| _reuse.pytest_configure(config) | ||
| _prefetch.pytest_configure(config) | ||
|
|
||
|
|
||
| def pytest_runtest_setup(item): | ||
| _reuse.pytest_runtest_setup(item) | ||
| _prefetch.pytest_runtest_setup(item) | ||
|
|
||
|
|
||
| def pytest_runtest_logreport(report): | ||
| # Reuse's failure fence (drain pools after a failed test); previously not | ||
| # wired in the fallback dirs at all. | ||
| _reuse.pytest_runtest_logreport(report) | ||
|
|
||
|
|
||
| def pytest_runtest_logfinish(nodeid, location): | ||
| _reuse.pytest_runtest_logfinish(nodeid, location) | ||
|
|
||
|
|
||
| def pytest_sessionfinish(session, exitstatus): | ||
| _reuse.pytest_sessionfinish(session, exitstatus) | ||
| _prefetch.pytest_sessionfinish(session, exitstatus) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| """Helpers shared by the MPI session reuse and session prefetch layers. | ||
|
|
||
| ``session_reuse.py`` (keeps pools alive across tests) and | ||
| ``session_prefetcher.py`` (spawns the next pool in the background) manage the | ||
| same object — a live ``MpiPoolSession`` handed to a test that did not spawn | ||
| it — so they share the same invariant: the worker-visible state a pool | ||
| freezes at spawn. Keeping it in one place means a fix applies to both layers. | ||
|
|
||
| Policy stays in the layers: what to DO with a snapshot mismatch (discard vs | ||
| proceed) is each layer's own decision. | ||
| """ | ||
|
|
||
| import os | ||
| import sys | ||
|
|
||
| # Workers freeze the parent environment AND sys.path at spawn time, so a | ||
| # pool spawned earlier must not be handed to a test that changed either | ||
| # (silently stale env / unimportable monkeypatched modules). Process | ||
| # bookkeeping that legitimately drifts between tests is ignored; a false | ||
| # mismatch only costs one synchronous rebuild. | ||
| _ENV_IGNORE = frozenset( | ||
| { | ||
| "PYTEST_CURRENT_TEST", # changes every test phase by design | ||
| "COLUMNS", | ||
| "LINES", | ||
| "PWD", | ||
| "OLDPWD", | ||
| "SHLVL", | ||
| "_", | ||
| } | ||
| ) | ||
|
|
||
|
|
||
| def _spawn_snapshot(): | ||
| """The worker-visible state a pool freezes at spawn: env + sys.path.""" | ||
| return ( | ||
| {k: v for k, v in os.environ.items() if k not in _ENV_IGNORE}, | ||
| list(sys.path), | ||
| ) | ||
|
|
||
|
|
||
| def _isinstance_transparent_shim(real_cls, factory): | ||
| """A seam replacement that intercepts construction but stays a real type. | ||
|
|
||
| The pool-creation seams used to hold a plain FUNCTION in place of | ||
| ``MpiPoolSession``. Library code that does ``isinstance(x, | ||
| MpiPoolSession)`` against the patched module attribute then raises | ||
| ``TypeError: isinstance() arg 2 must be a type`` — proxy.py's | ||
| killed-worker detection added exactly such a check and every bare | ||
| ``LLM()`` creation failed until it was worked around with an | ||
| exclusion-based match. This shim removes the hazard for good: a real | ||
| class whose metaclass routes construction to ``factory`` and | ||
| instance/subclass checks to ``real_cls``, so both usage patterns keep | ||
| working — including consumers added after this layer was written. | ||
| """ | ||
|
|
||
| class _SeamMeta(type): | ||
| def __call__(cls, *args, **kwargs): | ||
| return factory(*args, **kwargs) | ||
|
|
||
| def __instancecheck__(cls, obj): | ||
| return isinstance(obj, real_cls) | ||
|
|
||
| def __subclasscheck__(cls, sub): | ||
| return issubclass(sub, real_cls) | ||
|
|
||
| def __repr__(cls): | ||
| return f"<pool seam shim for {real_cls!r}>" | ||
|
|
||
| return _SeamMeta("MpiPoolSession", (), {}) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.