Refactoring: derive nixlUcxThreadPoolEngine from nixlUcxThreadEngine#1906
Refactoring: derive nixlUcxThreadPoolEngine from nixlUcxThreadEngine#1906iyastreb wants to merge 16 commits into
Conversation
|
👋 Hi iyastreb! Thank you for contributing to ai-dynamo/nixl. Your PR reviewers will review your contribution then trigger the CI to test your changes. 🚀 |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughUCX thread handling now creates shared progress threads only when enabled and workers exist, and thread-pool instances inherit the thread-engine’s notification and progress behavior instead of maintaining separate shared-thread state. ChangesUCX Thread Engine Refactor
Estimated code review effort: 3 (Moderate) | ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
/build |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/plugins/ucx/ucx_backend.h (1)
328-328: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winOverride
getNotifs()in the thread-pool engine.nixlUcxThreadPoolEnginecan still be created withenableProgTh == false && num_threads > 0, so inheritingnixlUcxThreadEngine::getNotifs()makes the null-thread_fallback callprogressLoop()while dedicated workers are already active. That can progress the same UCX workers concurrently.🤖 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 `@src/plugins/ucx/ucx_backend.h` at line 328, The thread-pool engine inherits getNotifs() from nixlUcxThreadEngine, which can incorrectly fall back to progressLoop() even when nixlUcxThreadPoolEngine has dedicated worker threads running. Override getNotifs() in nixlUcxThreadPoolEngine so notification handling uses the thread-pool path only and never starts the null-thread fallback that can progress UCX workers concurrently; update the override near nixlUcxThreadPoolEngine and align it with the existing thread-pool/progress logic in nixlUcxThreadEngine.
🤖 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.
Outside diff comments:
In `@src/plugins/ucx/ucx_backend.h`:
- Line 328: The thread-pool engine inherits getNotifs() from
nixlUcxThreadEngine, which can incorrectly fall back to progressLoop() even when
nixlUcxThreadPoolEngine has dedicated worker threads running. Override
getNotifs() in nixlUcxThreadPoolEngine so notification handling uses the
thread-pool path only and never starts the null-thread fallback that can
progress UCX workers concurrently; update the override near
nixlUcxThreadPoolEngine and align it with the existing thread-pool/progress
logic in nixlUcxThreadEngine.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 76f8d202-60e9-4b8d-808d-05c26446014e
📒 Files selected for processing (1)
src/plugins/ucx/ucx_backend.h
|
/build |
|
/build |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@src/plugins/ucx/ucx_backend.cpp`:
- Around line 366-368: Validate `num_threads` in `UcxBackend` before computing
`numSharedWorkers_` so it cannot exceed `getWorkers().size()`, and fail fast
with a runtime error if the requested thread count is invalid. Update the logic
around `shared_count` and the worker-indexing path in `UcxBackend::...` so it no
longer relies on `NIXL_ASSERT` for production safety, and ensure the derived
worker range used later when indexing workers is always bounds-checked.
In `@src/plugins/ucx/ucx_backend.h`:
- Around line 315-322: Move getSharedWorkersSize() back under the protected
section alongside appendNotif() in ucx_backend.h so it remains an internal
helper instead of a public API. Keep the UCX backend member grouping consistent
by preserving the intended public/protected/private layout, and make sure any
existing access by the pool still works through the protected override rather
than exposing it through the public interface.
🪄 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: ASSERTIVE
Plan: Enterprise
Run ID: 469a4e81-8e2e-47a6-b6f0-3394bff8ec44
📒 Files selected for processing (2)
src/plugins/ucx/ucx_backend.cppsrc/plugins/ucx/ucx_backend.h
|
/build |
|
/build |
|
/build |
|
🤖 CI Triage Agent — TL;DR: The build compiled and pushed the Docker image successfully; the job failed only in the "Allocate DL EP Environment" stage because Slurm could not allocate a GB200 node within its 1-hour Full analysisSummary: Stage "Allocate DL EP Environment" (node 183/200) failed after a Slurm Root cause: Implicated commit: none — not caused by commit [REDACTED:Hex High Entropy String]; failure is infrastructure (Slurm allocation). File: none (CI/infra: Slurm Suggested fix: Re-run the job when GB200 capacity is available. If these allocation timeouts recur, either (a) raise Related: none
|
|
🤖 CI Triage Agent — TL;DR: The "Run Nixlbench tests" stage hung for ~41 minutes (05:16:37 → 05:57:52) during UCCL/UCX engine teardown and was SIGTERM-killed (exit 143); the hang is in the UCX progress-thread destructor refactored by this PR (#1906, deriving Full analysisSummary: Jenkins Root cause: Not a slow test — a hang. Timeline evidence: the last application output is at Implicated commit: The PR under test, #1906 "Refactoring: derive nixlUcxThreadPoolEngine from nixlUcxThreadEngine" (head File: Suggested fix: In PR #1906, ensure the refactored destructor unconditionally signals the progress thread to stop and joins it, and that the shared vs. dedicated thread ownership isn't dropped/double-managed when Related: PR #1906 (#1906); prior fix in same path #1880 (
|
|
/build |
|
🤖 CI Triage Agent — TL;DR: The "Run Nixlbench tests" stage was killed (exit 143) after hanging ~43 minutes; the last real output was the first ETCD-runtime UCCL test ( Full analysisSummary: Jenkins Root cause: A hang, not slowness. Timestamps show continuous activity until 08:53:08.160Z ("Engine destroyed" + "Error/HUP on connection: 1.1.101.2:40351" for the first ETCD-runtime UCCL test, READ VRAM→VRAM). The very next loop iteration (UCCL READ VRAM→DRAM under ETCD) never printed even its "Connecting to ETCD" line. Then there is a ~17-minute dead gap until 09:10:16Z ("Cannot contact ... ChannelClosedException") and finally a kill at 09:36:22Z ("Sending interrupt signal / Killing processes", exit 143). The UCCL RDMA engine hung during teardown/re-initialization — one of the paired nixlbench workers destroyed its engine while the peer was left blocked (the ASIO variants of the same UCCL cases each finished in ~10s, so the problem is specific to the UCCL backend's shutdown/re-init between iterations, exposed under the ETCD runtime). The subsequent "export failed" / channel-closed lines are downstream symptoms of the node being torn down, not the cause. Implicated commit: unknown for build #2713's PR #1906 (commit File: Suggested fix: Investigate the UCCL Engine destroy → next-iteration re-init path for a deadlock/blocked accept. The teardown logs show one worker reaching "Engine destroyed" while the peer's background accept ("Waiting to accept incoming connection...") appears not to unblock; add a bounded timeout/interrupt to the UCCL accept and connection-teardown so a destroyed peer cannot leave the other worker blocked forever. As an interim CI mitigation, wrap each nixlbench invocation with a per-test Related: PR #1724 (UCCL crash fix); prior UCCL work PR #1428, #1271, #1151, #895. |
|
/build |
|
🤖 CI Triage Agent — TL;DR: The aarch64 Full analysisSummary: Jenkins build #2345, stage 501 ( Root cause: A process hang, not a timeout. The stage log shows continuous test progress up to Implicated commit: File: Suggested fix: Do not raise the CI time limit — this is a hang. Investigate the endpoint force-close logic added in Related: PR #1906 (this build); commit/PR #1846 / re-land PR #1950 ("Added option to forcibly close UCP endpoints"); prior related fix PR #1880 ("fix infinite loop dropping pending requests on dedicated-thread exit"). |
|
🤖 CI Triage Agent — TL;DR: The Python-test stage ( Full analysisSummary: Root cause: When Implicated commit: No single code commit broke this; it's an environment/port-collision issue. Relevant context: File: test/python/test_nixl_api.py:22 (config construction for Suggested fix: Make the listener use a non-fixed port in this test — pass an OS-assigned (ephemeral, port 0) or per- Related: PR #1439 (OS-assigned ports for metadata listener); PR #1501 (added |
|
🤖 CI Triage Agent — TL;DR: The "Allocate DL EP Environment" stage failed because a Slurm Full analysisSummary: Stage 200 (Allocate DL EP Environment) failed at Slurm node allocation; the earlier compile/image stages all succeeded and stage 124's failure was just the parallel build-matrix being stopped alongside it. Root cause: Implicated commit: none — not caused by commit [REDACTED:Hex High Entropy String] or PR #1906; failure is in CI infrastructure resource allocation. File: Jenkins pipeline Suggested fix: Retry the build — this is a transient GB200 cluster-capacity/queue issue. If it recurs, (1) check Related: none (no matching issues/PRs for this allocation failure).
|
|
🤖 CI Triage Agent — TL;DR: The "Build sanity image" stage (#470) failed because Full analysisSummary: aarch64 "Build sanity image" stage failed at Root cause: Transient network outage on the Jenkins build node. The Implicated commit: none — infrastructure failure, unrelated to commit [REDACTED:Hex High Entropy String] / PR #1906. File: Suggested fix:
Related: none found.
|
|
/build |
|
🤖 CI Triage Agent — TL;DR: The "Run CPP tests" stage exited 42 because the gtest CI harness treats the benign environmental warning Full analysisSummary: Stages 203 and 242 ("Run CPP tests") failed with exit code 42; 69/154 tests reported failed, almost all due to a UCX build lacking CUDA/IB support in the test container. Root cause: The UCX in the test image was built/loaded without CUDA and accelerated-IB transports ( Implicated commit: unknown (recent history on File: Suggested fix: Fix the test container's UCX so it is built with CUDA and IB/RDMA transport support (investigate the failing Related: none found. |
|
🤖 CI Triage Agent — TL;DR: The "Run Nixlbench tests" stage was killed by Jenkins (exit 143) after an ~18-minute hang, not a slow test; the first UCCL+ETCD benchmark hung during engine teardown (one Full analysisSummary: Nixlbench stage (node 356) hung during teardown of the first UCCL+ETCD benchmark and was SIGTERM-killed after ~18 min of no output. Root cause: Engine/worker shutdown deadlock. At 06:47:45–48 both workers reached "Destroying Engine…"; one printed "Engine destroyed" but the peer hit Implicated commit: PR #1906 (adac02f, "Refactoring: derive nixlUcxThreadPoolEngine from nixlUcxThreadEngine") — the change under test; closely related prior fix is 0225cd5 (#1880, "ucx: fix infinite loop dropping pending requests on dedicated-thread exit") by Eylon Eliyahu Krause, same shutdown code path. File: UCX engine shutdown path exercised via Suggested fix: Reproduce the UCCL+ETCD READ VRAM→VRAM case and capture a stack trace (gdb/py-spy) of the stuck Related: PR #1906 (#1906); PR #1880 (#1880); PR #1846 (#1846, forcibly close UCP endpoints). |
|
🤖 CI Triage Agent — TL;DR: The "Run CPP tests" stage crashed (SIGABRT, exit 134) in Full analysisSummary: Jenkins Root cause: UCX on test node Implicated commit: unknown — no code change in the failing test path is implicated; the failure originates from the UCX runtime/device configuration on node File: Suggested fix:
Related: PR #1869 (CI base image switch to pytorch + CUDA 13.3); PR #1743 (run gtest in single process). No existing issue matches the "No such device" UCX worker failure. |
What?
To unify the code and reuse the same functions
It's pre-requisite for completions API PR
Summary by CodeRabbit
Bug Fixes
Refactor