Skip to content

[https://nvbugs/6523767][fix] Size MPI worker-identity barrier timeout to cover worker bootstrap - #16971

Merged
sunnyqgg merged 3 commits into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6523767
Jul 31, 2026
Merged

[https://nvbugs/6523767][fix] Size MPI worker-identity barrier timeout to cover worker bootstrap#16971
sunnyqgg merged 3 commits into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6523767

Conversation

@trtllm-agent

@trtllm-agent trtllm-agent commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Root cause: MpiPoolSession(wait_shutdown=True) collects worker identities by submitting a barrier task to a freshly built MPIPoolExecutor and waiting 60s for all N results. Because mpi4py spawns lazily from its manager thread, that first submission actually has to cover the entire worker bootstrap — process spawn plus import tensorrt_llm, which the repo elsewhere measures at ~50-65s idle and up to ~117s on a contended node. On a busy B200 post-merge machine the 60s deadline expired with 0/N identities collected, so the fail-closed path tore the pool down and raised, aborting the test.
  • Fix: Raised the barrier deadline to a default of 300s, sized against worker bootstrap cost rather than barrier latency, and factored it into _identity_barrier_timeout() with a TRTLLM_MPI_IDENTITY_TIMEOUT override that rejects unparsable, non-positive, and NaN values in favor of the default. The fail-closed behavior and its error message are kept intentionally — the message now reports the effective deadline and points at the override — because handing out a pool that cannot honor the wait_shutdown contract would trade a loud failure for a silent one. Unit tests assert the default exceeds the slowest measured bootstrap and cover the env-override parsing table.
  • Automated fix generated by repair-bot

Test plan

  • Verify fix on the same GPU type as the original failure
  • Check for regressions in related tests

Links

Dev Engineer Review

  • Increased MPI worker-identity barrier wait timeout from a hardcoded 60s to a configurable value:
    • Added _DEFAULT_IDENTITY_TIMEOUT: float = 300.0 and _identity_barrier_timeout() -> float in tensorrt_llm/llmapi/mpi_session.py.
    • _identity_barrier_timeout() reads TRTLLM_MPI_IDENTITY_TIMEOUT and validates it as a finite, positive float; invalid/unparseable/NaN/non-positive values fall back to the 300s default (with warning/fallback behavior preserved).
    • Updated MpiPoolSession._collect_worker_identities to use the computed timeout for identity-barrier futures instead of 60.0.
    • Preserved fail-closed behavior, and enhanced RuntimeError messaging to include the effective deadline and explicitly reference TRTLLM_MPI_IDENTITY_TIMEOUT for diagnosis of slow-but-healthy bootstrap.
  • Aligned session prefetch/shadow-build timing with the MPI identity timeout:
    • Updated tests/test_common/session_prefetcher.py to derive shadow build join/drain budget from MPI identity-barrier logic when available, falling back to TRTLLM_MPI_IDENTITY_TIMEOUT.
    • Refactored SessionPrefetcher draining coordination (_drain_lock, _build_timed_out) and changed _drain to accept timeout: float | None = None.
    • Changed take() behavior to always route through _drain() without the previous wrong-size in-flight early-discard logic.
    • Tightened failure-path and lifecycle ordering: timeout/programming errors propagate directly; shadow/restock is scheduled only after the real session is successfully obtained; on misses, it avoids retry/degrade flows by constructing the synchronous real_cls(..., wait_shutdown=True) session directly.
  • Updated session reuse behavior to match the new prefetch miss/exception semantics:
    • tests/test_common/session_reuse.py now avoids converting prefetcher failures into synchronous-pool fallback at the seam and removes the “spawn failed, retrying once” retry attempt; scheduling/restocking is ordered after real creation and remains best-effort.

QA Engineer Review

Test code changes (files under tests/ touched):

  • tests/unittest/llmapi/test_mpi_session.py
    • Covered identity-collection timeout/deadline behavior via:
      • test_identity_collection_uses_configured_timeout
      • test_identity_timeout_covers_worker_bootstrap
      • test_identity_timeout_env_override
      • test_prefetch_fallback_identity_timeout_matches_mpi_default
      • plus fail-closed/timeouts related assertions:
        • test_identity_collection_fails_closed_on_timeout
        • test_identity_collection_fails_closed_on_duplicate_pids
  • tests/unittest/llmapi/test_session_prefetcher.py
    • Verified identity-derived shadow wait budget + concurrency/terminal timeout semantics:
      • test_shadow_wait_budget_tracks_identity_timeout
      • test_shadow_wait_budget_handles_partially_loaded_mpi_module
      • test_take_wrong_size_in_flight_waits_before_miss
      • test_take_timeout_is_terminal_until_build_exits
      • test_concurrent_take_timeout_waits_only_once
    • Failure semantics:
      • test_factory_spawn_failure_propagates_without_retry
  • tests/unittest/llmapi/test_session_reuse.py
    • Failure-path coverage for new propagation/no-retry behavior:
      • test_shadow_timeout_does_not_start_sync_pool
      • test_prefetcher_programming_error_propagates
      • test_spawn_failure_propagates_without_retry
  • Support code updated (not direct unit tests):
    • tests/test_common/session_prefetcher.py, tests/test_common/session_reuse.py

Integration mapping (tests/integration/test_lists/) to the touched unit tests:

  • Found CI list coverage only for tests/unittest/llmapi/test_mpi_session.py:
    • tests/integration/test_lists/test-db/l0_dgx_h100.yml: unittest/llmapi/test_mpi_session.py::test_llmapi_launch_multiple_tasks
    • tests/integration/test_lists/test-db/l0_a100.yml: unittest/llmapi/test_mpi_session.py ISOLATION
  • No matching test-db/qa entries were found for the other touched unit test modules (test_session_prefetcher.py, test_session_reuse.py) from the searches performed.

Verdict: needs follow-up.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b39413cb-fcd9-4381-b7cc-8df7bcb54a3e

📥 Commits

Reviewing files that changed from the base of the PR and between 42a9149 and 97162f3.

📒 Files selected for processing (6)
  • tensorrt_llm/llmapi/mpi_session.py
  • tests/test_common/session_prefetcher.py
  • tests/test_common/session_reuse.py
  • tests/unittest/llmapi/test_mpi_session.py
  • tests/unittest/llmapi/test_session_prefetcher.py
  • tests/unittest/llmapi/test_session_reuse.py

Walkthrough

MPI worker identity collection now uses a validated configurable timeout. Session prefetching derives shadow-build deadlines from that timeout, propagates acquisition failures, changes synchronous fallback behavior, and updates cleanup and reuse tests.

Changes

MPI session timeout configuration

Layer / File(s) Summary
Identity timeout resolution
tensorrt_llm/llmapi/mpi_session.py, tests/unittest/llmapi/test_mpi_session.py
Adds validated TRTLLM_MPI_IDENTITY_TIMEOUT handling, a default fallback, and coverage for configured and invalid values.
Worker identity barrier integration
tensorrt_llm/llmapi/mpi_session.py, tests/unittest/llmapi/test_mpi_session.py
Uses the resolved timeout for identity collection and includes the deadline and override variable in incomplete-collection errors.

Session prefetch and reuse behavior

Layer / File(s) Summary
Shadow build timeout lifecycle
tests/test_common/session_prefetcher.py, tests/unittest/llmapi/test_session_prefetcher.py
Derives shadow-build wait budgets from MPI identity timeout logic, serializes drains, raises TimeoutError for timed-out acquisition drains, and suppresses cleanup timeouts during disposal.
Synchronous fallback and restocking
tests/test_common/session_reuse.py, tests/test_common/session_prefetcher.py, tests/unittest/llmapi/test_session_reuse.py, tests/unittest/llmapi/test_session_prefetcher.py
Removes spawn retries, propagates prefetch and construction failures, and schedules replacement shadows only after successful synchronous pool creation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: brnguyen2

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: extending the MPI worker-identity barrier timeout to cover worker bootstrap.
Description check ✅ Passed The description clearly summarizes the bug, fix, tests, and link, though it does not follow the template headings exactly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/unittest/llmapi/test_mpi_session.py (1)

282-299: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Strengthen timeout coverage. Assert the default 300s path explicitly, and add a test that captures the timeout passed from _collect_worker_identities() to futures_wait.

  • Added: test_identity_timeout_covers_worker_bootstrap, test_identity_timeout_env_override
  • Modified/removed: none
  • Test-list coverage: tests/unittest/llmapi/test_mpi_session.py is already listed as ISOLATION in tests/integration/test_lists/test-db/l0_a100.yml
  • Verdict: sufficient
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/llmapi/test_mpi_session.py` around lines 282 - 299, Strengthen
timeout coverage by asserting the unset environment path in
test_identity_timeout_covers_worker_bootstrap returns the explicit 300-second
default, while retaining the bootstrap lower-bound check. Add a focused test
around _collect_worker_identities that mocks or intercepts futures_wait and
verifies it receives the timeout from _identity_barrier_timeout(), including the
configured environment override.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/llmapi/mpi_session.py`:
- Around line 241-244: Update the timeout parsing logic around the float
conversion to accept overrides only when math.isfinite(value) and value > 0.
Preserve rejection of NaN, zero, and negative values, and extend the timeout
tests to cover explicit infinity and overflow inputs such as "1e309".

---

Nitpick comments:
In `@tests/unittest/llmapi/test_mpi_session.py`:
- Around line 282-299: Strengthen timeout coverage by asserting the unset
environment path in test_identity_timeout_covers_worker_bootstrap returns the
explicit 300-second default, while retaining the bootstrap lower-bound check.
Add a focused test around _collect_worker_identities that mocks or intercepts
futures_wait and verifies it receives the timeout from
_identity_barrier_timeout(), including the configured environment override.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b0fceb6a-b813-41df-b9d2-50760cfde64e

📥 Commits

Reviewing files that changed from the base of the PR and between f9ac468 and 2a64996.

📒 Files selected for processing (2)
  • tensorrt_llm/llmapi/mpi_session.py
  • tests/unittest/llmapi/test_mpi_session.py

Comment thread tensorrt_llm/llmapi/mpi_session.py

@allisonlim-nv allisonlim-nv left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM; timeout size for MPI worker extended to 300s, env override, fails if unable to verify workers are healthy.

@sunnyqgg

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62368 [ run ] triggered by Bot. Commit: 2a64996 Link to invocation

@sunnyqgg
sunnyqgg requested a review from a team as a code owner July 29, 2026 03:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
tests/test_common/session_prefetcher.py (2)

74-91: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded _FALLBACK_IDENTITY_TIMEOUT can silently drift from the real default.

_FALLBACK_IDENTITY_TIMEOUT = 300.0 mirrors mpi_session._DEFAULT_IDENTITY_TIMEOUT by literal value, not by reference (deliberately, per the docstring, to avoid an eager tensorrt_llm import). If the lower-level default ever changes, this fallback — used exactly when mpi_session isn't loaded yet — will silently disagree and compute an incorrect wait budget.

Consider adding a lightweight cross-check test (e.g., import tensorrt_llm.llmapi.mpi_session._DEFAULT_IDENTITY_TIMEOUT in a test and assert equality with this constant) so a future change to one default fails loudly instead of drifting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_common/session_prefetcher.py` around lines 74 - 91, Add a
lightweight test covering `_FALLBACK_IDENTITY_TIMEOUT` and the lower-level
`tensorrt_llm.llmapi.mpi_session._DEFAULT_IDENTITY_TIMEOUT`, asserting both
defaults remain equal. Keep the lazy-import behavior in
`_fallback_identity_timeout` unchanged while ensuring future default changes
fail the test instead of silently diverging.

435-477: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing return-type annotations on reworked _drain/take.

_drain(self, timeout: float | None = None): and take(self, spec: int): are both part of this rework (adding the optional timeout param and the new TimeoutError-raising behavior) but neither declares a return type, contrary to the repo guideline requiring every function be annotated.

✏️ Suggested annotations
-    def _drain(self, timeout: float | None = None):
+    def _drain(self, timeout: float | None = None) -> "_Built | None":
-    def take(self, spec: int):
+    def take(self, spec: int) -> "object | None":

If importing the real session type is undesirable at module load (per the "do not import TensorRT-LLM here" constraint), consider a TYPE_CHECKING-guarded import to get a precise type instead of object.

As per coding guidelines: "Annotate every function, use None for non-returning functions, avoid Any and unnecessary type ignores... use Literal, overload, TypeVar, or Protocol when appropriate."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_common/session_prefetcher.py` around lines 435 - 477, Add explicit
return-type annotations to the reworked _drain and take methods, using the
precise session/prefetch result types already established by the module; if that
type requires the real session import, place it behind TYPE_CHECKING. Preserve
_drain’s completed-build-or-None result and take’s prefetched-session-or-None
behavior, while retaining its TimeoutError path.

Source: Coding guidelines

tests/test_common/session_reuse.py (1)

366-383: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Broad except Exception on the new prefetch fallback path.

The new except Exception as e: # prefetch is an optimization: fall back (flagged by Ruff BLE001) will also swallow programming errors in prefetcher.take() (e.g. AttributeError, TypeError) and silently degrade to a synchronous spawn instead of surfacing the bug. The TimeoutError case is already split out correctly above it; consider narrowing the remaining catch to the concrete failure modes take() can legitimately raise (or at least log at a level that makes such fallbacks visible/alertable).

As per coding guidelines: "Catch specific exceptions instead of using broad or bare exception handling such as except:."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_common/session_reuse.py` around lines 366 - 383, Narrow the
generic exception handler around prefetcher.take in the prefetcher fallback path
to the concrete expected prefetch failure exceptions, while preserving separate
TimeoutError propagation and synchronous fallback behavior. Do not swallow
programming errors such as AttributeError or TypeError; let unexpected
exceptions surface.

Sources: Coding guidelines, Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/test_common/session_prefetcher.py`:
- Around line 74-91: Add a lightweight test covering
`_FALLBACK_IDENTITY_TIMEOUT` and the lower-level
`tensorrt_llm.llmapi.mpi_session._DEFAULT_IDENTITY_TIMEOUT`, asserting both
defaults remain equal. Keep the lazy-import behavior in
`_fallback_identity_timeout` unchanged while ensuring future default changes
fail the test instead of silently diverging.
- Around line 435-477: Add explicit return-type annotations to the reworked
_drain and take methods, using the precise session/prefetch result types already
established by the module; if that type requires the real session import, place
it behind TYPE_CHECKING. Preserve _drain’s completed-build-or-None result and
take’s prefetched-session-or-None behavior, while retaining its TimeoutError
path.

In `@tests/test_common/session_reuse.py`:
- Around line 366-383: Narrow the generic exception handler around
prefetcher.take in the prefetcher fallback path to the concrete expected
prefetch failure exceptions, while preserving separate TimeoutError propagation
and synchronous fallback behavior. Do not swallow programming errors such as
AttributeError or TypeError; let unexpected exceptions surface.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a5be9bb4-5193-4279-ac35-b5409c59fa24

📥 Commits

Reviewing files that changed from the base of the PR and between 2a64996 and bf19b88.

📒 Files selected for processing (6)
  • tensorrt_llm/llmapi/mpi_session.py
  • tests/test_common/session_prefetcher.py
  • tests/test_common/session_reuse.py
  • tests/unittest/llmapi/test_mpi_session.py
  • tests/unittest/llmapi/test_session_prefetcher.py
  • tests/unittest/llmapi/test_session_reuse.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tensorrt_llm/llmapi/mpi_session.py

@sunnyqgg

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62411 [ run ] triggered by Bot. Commit: 42a9149 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62368 [ run ] completed with state ABORTED. Commit: 2a64996

Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62411 [ run ] completed with state FAILURE. Commit: 42a9149
/LLM/main/L0_MergeRequest_PR pipeline #50570 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@sunnyqgg

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62489 [ run ] triggered by Bot. Commit: 42a9149 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62489 [ run ] completed with state SUCCESS. Commit: 42a9149
/LLM/main/L0_MergeRequest_PR pipeline #50636 completed with status: 'SUCCESS'
Pipeline passed with automatic retried tests. Check the rerun report for details.

CI Report

Link to invocation

HandongLi-01 and others added 3 commits July 30, 2026 05:37
…otstrap

The wait_shutdown identity barrier's hardcoded 60s deadline actually bounds
the entire worker bootstrap, not the barrier: MPIPoolExecutor() returns
immediately because mpi4py spawns from a background manager thread, so the
first submit() + futures_wait pays process spawn plus 'import tensorrt_llm'.
That bootstrap is ~50-65s on an idle node and up to ~117s on a contended one,
so a healthy-but-slow node fails closed with 0/N identities at ~61s.

Size the deadline against the bootstrap ceiling the repo already measures
(session_prefetcher.py budgets 180s for the same work) and make it tunable
via TRTLLM_MPI_IDENTITY_TIMEOUT, which the TRTLLM-prefix env filter in
_start_mpi_pool forwards to workers automatically. Fail-closed teardown is
unchanged, so genuinely wedged pools are still rejected rather than handed
out with the contract silently downgraded.

Fixing this library-side covers both affected call paths, including
SessionReuseCache.acquire's zero-retry branch that every AutoDeploy node id
takes.

Signed-off-by: handongl <handongl@nvidia.com>
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6523767 branch from 42a9149 to 97162f3 Compare July 30, 2026 14:20
@sunnyqgg
sunnyqgg enabled auto-merge (squash) July 31, 2026 05:26
@sunnyqgg

Copy link
Copy Markdown
Collaborator

/bot run --help

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62971 Bot args parsing error: usage: /bot [-h]
{run,kill,skip,submit,reviewers,reuse-pipeline,reuse-review} ...
/bot: error: unrecognized arguments: --help

Link to invocation

@sunnyqgg

Copy link
Copy Markdown
Collaborator

/bot run reuse-pipeline

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62983 Bot args parsing error: usage: /bot [-h]
{run,kill,skip,submit,reviewers,reuse-pipeline,reuse-review} ...
/bot: error: unrecognized arguments: reuse-pipeline

Link to invocation

@sunnyqgg

Copy link
Copy Markdown
Collaborator

/bot reuse-pipeline

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62984 [ reuse-pipeline ] triggered by Bot. Commit: 97162f3 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62984 [ reuse-pipeline ] completed with state SUCCESS. Commit: 97162f3
Reusing PR_Github #62489 for commit 97162f3

Link to invocation

@sunnyqgg
sunnyqgg merged commit dc7f325 into NVIDIA:main Jul 31, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants