Skip to content

PLUGINS/UCX: Add scatter-gather list (SGL) put path - #1835

Merged
michal-shalev merged 15 commits into
ai-dynamo:mainfrom
michal-shalev:ucx-sgl-put
Aug 4, 2026
Merged

michal-shalev merged 15 commits into
ai-dynamo:mainfrom
michal-shalev:ucx-sgl-put

Conversation

@michal-shalev

@michal-shalev michal-shalev commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

What?

Add a UCX scatter-gather (SGL) put path.

Why?

Posting one UCX request per descriptor is wasteful for multi-element writes. An SGL put hands UCX the whole descriptor list in one call, reducing per-element overhead.

How?

Off by default, gated at two layers:

  • Build-time: meson.build probes for ucp_dt_local_sgl_t and defines HAVE_UCX_SGL_API only when UCX exposes the SGL API. All SGL code is #ifdef-guarded.
  • Run-time: NIXL_UCX_SGL_ENABLE (default false) toggles it; if set on a build without SGL support, it warns and falls back to the per-descriptor path.

For NIXL_WRITE, a new sglXfer gathers the descriptor range into parallel arrays (addrs, lengths, memhs, rkeys) kept on the request handle. sendXferRange short-circuits to sendXferSgl, issuing one postSgl (ucp_put_nbx + ucp_dt_make_sgl()) and a single flushEp per batch.

Summary by CodeRabbit

  • New Features
    • Added optional UCX scatter-gather list (SGL) offload for write transfers.
    • When supported and enabled, write operations are submitted using SGL for more efficient handling across multiple segments.
  • Compatibility
    • UCX SGL support is auto-detected at build time; builds without it won’t include the feature.
    • Runtime enablement is controlled by NIXL_UCX_SGL_ENABLE; if SGL isn’t compiled in, it is forced off with a warning.
    • When SGL can’t be used, the system falls back to the existing transfer behavior.

@michal-shalev michal-shalev self-assigned this Jun 25, 2026
@michal-shalev
michal-shalev requested review from a team, brminich, gleon99 and yosefe as code owners June 25, 2026 00:28
@copy-pr-bot

copy-pr-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@michal-shalev
michal-shalev marked this pull request as draft June 25, 2026 00:28
@github-actions

Copy link
Copy Markdown

👋 Hi michal-shalev! Thank you for contributing to ai-dynamo/nixl.

Your PR reviewers will review your contribution then trigger the CI to test your changes.

🚀

@coderabbitai

coderabbitai Bot commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds optional UCX SGL API detection, transfer descriptors, endpoint posting helpers, runtime enablement, and an SGL-based write-transfer path with request and flush tracking.

Changes

UCX SGL support

Layer / File(s) Summary
Feature gate and SGL contracts
meson.build, src/plugins/ucx/meson.build, src/plugins/ucx/ucx_sgl.*, src/plugins/ucx/ucx_utils.h, src/plugins/ucx/ucx_backend.h
Meson detects the UCX SGL type, builds the implementation, and adds guarded SGL interfaces and engine state.
SGL state and endpoint posting
src/plugins/ucx/ucx_sgl.*, src/plugins/ucx/ucx_utils.*
Per-segment addresses, lengths, memory handles, and rkeys are stored, then passed to UCX through SGL descriptors.
Runtime routing and request handling
src/plugins/ucx/ucx_backend.cpp
Configured write transfers use SGL preparation and submission, including subranges, request tracking, flush handling, and named reservation sizing.

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

Sequence Diagram(s)

sequenceDiagram
  participant nixlUcxEngine
  participant sglXfer
  participant nixlUcxEp
  participant UCX

  nixlUcxEngine->>sglXfer: build local and remote segment state
  nixlUcxEngine->>nixlUcxEp: postSgl(localView, remoteView, count, req)
  nixlUcxEp->>UCX: ucp_put_nbx(...)
  UCX-->>nixlUcxEp: request pointer or completion status
  nixlUcxEp-->>nixlUcxEngine: NIXL_IN_PROG or completion status
Loading

Suggested reviewers: brminich

🚥 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 clearly summarizes the main change: adding an optional UCX SGL put path.
Description check ✅ Passed The description follows the template and includes What, Why, and How with the key gating and design details.
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: 3

🤖 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 1323-1325: The SGL fast path in ucx_backend.cpp currently skips
the per-endpoint batching logic in the send path. Update the NIXL_WRITE branch
in the transfer routine (the block that calls sendXferSgl) so it only takes this
route when the full remote range remote[start_idx:end_idx] resolves to a single
connection, or move the batching/connection-homogeneity check into sendXferSgl
itself. Use the existing transfer flow and metadata helpers in this backend to
verify the range before returning the SGL path.
- Around line 1249-1293: The sendXferSgl() path is using a single
getConnection(remote_agent) for the whole range, which can post remote
addrs/rkeys through the wrong UCX endpoint when descriptors span multiple
connections. Update ucx_backend.cpp so the SGL send is scoped to one connection
by grouping descriptors by rmd->conn (like the non-SGL batching logic) and
posting each group on its own conn->getEp(worker_id), or detect mixed
connections and fall back to the non-SGL path. Keep the existing
local_sgl/remote_sgl setup but build it per connection instead of once for the
whole range.

In `@src/plugins/ucx/ucx_utils.h`:
- Around line 112-117: The public endpoint API `postSgl()` in `ucx_utils.h`
needs a Doxygen block documenting the SGL lifetime contract. Add a `/** ... */`
comment above `postSgl()` that clearly states the caller-owned
`ucp_dt_local_sgl_t` and `ucp_dt_remote_sgl_t` arrays must remain valid until
the associated request completes, so users know the stored UCX pointers must
outlive completion. Use the function name `postSgl()` and the `nixlUcxReq`
request type in the comment to make the ownership and completion requirement
explicit.
🪄 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: 8909565d-7350-4d42-8b9f-c50ca03ce3eb

📥 Commits

Reviewing files that changed from the base of the PR and between a9f456b and 61383da.

📒 Files selected for processing (5)
  • meson.build
  • src/plugins/ucx/ucx_backend.cpp
  • src/plugins/ucx/ucx_backend.h
  • src/plugins/ucx/ucx_utils.cpp
  • src/plugins/ucx/ucx_utils.h

Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
Comment thread src/plugins/ucx/ucx_utils.h Resolved
Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
@michal-shalev
michal-shalev force-pushed the ucx-sgl-put branch 2 times, most recently from 2218f6c to 9610c29 Compare July 16, 2026 19:10
@michal-shalev
michal-shalev requested a review from ColinNV July 16, 2026 19:33
@michal-shalev michal-shalev changed the title PLUGINS/UCX: add scatter-gather (SGL) put path PLUGINS/UCX: add scatter-gather list (SGL) put path Jul 16, 2026
@michal-shalev michal-shalev changed the title PLUGINS/UCX: add scatter-gather list (SGL) put path PLUGINS/UCX: Add scatter-gather list (SGL) put path Jul 16, 2026
@michal-shalev
michal-shalev marked this pull request as ready for review July 16, 2026 19:42

@ColinNV ColinNV 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.

Test coming separately?

Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
Comment thread src/plugins/ucx/ucx_backend.h Resolved
Comment thread src/plugins/ucx/ucx_backend.cpp Resolved

@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

🤖 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_sgl.h`:
- Around line 33-39: Add a Doxygen-style documentation block immediately before
the public sglXfer class declaration, describing its ownership semantics and
stating that the arrays referenced by the UCX request must outlive that request.
Keep the constructor and class behavior unchanged.
🪄 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: c41315bf-f0fc-449f-810c-1c4ddde17bce

📥 Commits

Reviewing files that changed from the base of the PR and between a647483 and 6934016.

📒 Files selected for processing (4)
  • src/plugins/ucx/meson.build
  • src/plugins/ucx/ucx_backend.cpp
  • src/plugins/ucx/ucx_sgl.cpp
  • src/plugins/ucx/ucx_sgl.h

Comment thread src/plugins/ucx/ucx_sgl.h Resolved
@michal-shalev
michal-shalev enabled auto-merge (squash) July 30, 2026 15:26
@michal-shalev

Copy link
Copy Markdown
Contributor Author

/build

@iyastreb

Copy link
Copy Markdown
Contributor

I have just submitted PR for perf degradation caused by previous SGL changes
#2017
Please check that we don't have the similar issue in this PR

Comment thread src/plugins/ucx/ucx_backend.cpp Resolved
@michal-shalev
michal-shalev disabled auto-merge August 3, 2026 14:18
@michal-shalev

Copy link
Copy Markdown
Contributor Author

/build

@michal-shalev
michal-shalev requested a review from iyastreb August 3, 2026 15:26
@michal-shalev

Copy link
Copy Markdown
Contributor Author

/build

@svc-nixl

svc-nixl commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agent — nixl-ci-dl-gpu-ep · commit c92dd114

TL;DR: The build compiled fine; the job failed because the Slurm salloc for a GB200 node (gb200nvl72_cx8) sat queued for the full --immediate=3600 (1 hour) window and gave up with "Unable to allocate resources: Connection timed out" — a cluster-capacity/infra issue, not a code defect.

Full analysis

Summary: Stage 226 "Allocate DL EP Environment" (ucx-v1.22.x branch) failed when Slurm could not grant a compute node within the immediate-allocation deadline.

Root cause: After a successful NIXL/nixlbench build and Docker image push (~17:04), the pipeline ran salloc -N 1 -p gb200nvl72_cx8 ... --immediate=3600 --time=01:30:00 against dlcluster.nvidia.com. Job 1736675 was queued and waiting for resources; ~60 minutes later (18:05:05) Slurm returned error: Unable to allocate resources: Connection timed out. The 60-minute silent gap corresponds exactly to the --immediate=3600 wait timeout expiring — the scheduler never freed a GB200 exclusive node for this parallel branch. (The sibling ucx-master branch, stage 209, did secure a node, confirming contention rather than a per-branch bug.) The FAILURE flag on stage 151 is inherited from this downstream allocation failure, not a compile error — its log shows a clean build.

Implicated commit: unknown — not caused by commit c92dd11 or PR #1835; this is a Slurm scheduling/capacity failure external to the code.

File: N/A (CI infra — Slurm allocation step invoking salloc on dlcluster.nvidia.com, partition gb200nvl72_cx8)

Suggested fix: This is an infrastructure/capacity retry situation, not a code fix. Concretely: (1) re-run the build — the queue was simply full of GB200 jobs; (2) if this recurs, raise the --immediate window or switch to a blocking salloc with a bounded queue-wait and automatic retry/backoff so a transient capacity crunch doesn't fail the whole pipeline; (3) consider gating the DL-EP GPU stage so a scheduler capacity timeout is reported as "infra/unstable" rather than a hard build failure. Do not treat this as a bug in PR #1835.

Related: none

@michal-shalev

Copy link
Copy Markdown
Contributor Author

/build

@michal-shalev

Copy link
Copy Markdown
Contributor Author

I have just submitted PR for perf degradation caused by previous SGL changes #2017 Please check that we don't have the similar issue in this PR

Good catch on the NIXL issue, and thanks for fixing it in #2017.

PR #2017 addresses a pre-existing issue in the default NIXL path that became more noticeable after openucx/ucx#11258 increased the size of ucp_request_param_t, so describing it as a performance degradation caused by previous SGL changes is somewhat misleading.

PR #1835 introduces a separate, optional SGL path behind an environment variable and does not modify the default execution path. If you believe there is a similar issue in this PR, please point to the specific code path or demonstrate the regression here.

@michal-shalev

Copy link
Copy Markdown
Contributor Author

/build

@michal-shalev

Copy link
Copy Markdown
Contributor Author

/ok to test 514c03e

@michal-shalev
michal-shalev enabled auto-merge (squash) August 4, 2026 08:34
@michal-shalev
michal-shalev merged commit 32794e9 into ai-dynamo:main Aug 4, 2026
19 checks passed
@michal-shalev
michal-shalev deleted the ucx-sgl-put branch August 4, 2026 09:05
hxieustc pushed a commit to hxieustc/nixl that referenced this pull request Oct 6, 2026
## What?
Add a UCX scatter-gather (SGL) put path.

## Why?
Posting one UCX request per descriptor is wasteful for multi-element
writes. An SGL put hands UCX the whole descriptor list in one call,
reducing per-element overhead.

## How?
Off by default, gated at two layers:
- **Build-time**: `meson.build` probes for `ucp_dt_local_sgl_t` and
defines `HAVE_UCX_SGL_API` only when UCX exposes the SGL API. All SGL
code is `#ifdef`-guarded.
- **Run-time**: `NIXL_UCX_SGL_ENABLE` (default `false`) toggles it; if
set on a build without SGL support, it warns and falls back to the
per-descriptor path.

For `NIXL_WRITE`, a new `sglXfer` gathers the descriptor range into
parallel arrays (addrs, lengths, memhs, rkeys) kept on the request
handle. `sendXferRange` short-circuits to `sendXferSgl`, issuing one
`postSgl` (`ucp_put_nbx` + `ucp_dt_make_sgl()`) and a single `flushEp`
per batch.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added optional UCX scatter-gather list (SGL) offload for write
transfers.
* When supported and enabled, write operations are submitted using SGL
for more efficient handling across multiple segments.
* **Compatibility**
* UCX SGL support is auto-detected at build time; builds without it
won’t include the feature.
* Runtime enablement is controlled by `NIXL_UCX_SGL_ENABLE`; if SGL
isn’t compiled in, it is forced off with a warning.
* When SGL can’t be used, the system falls back to the existing transfer
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

This branch was previously deployed

1 inactive deployment
SWX_AWS — 514c03ed Deployed Aug 4, 2026 by copy-pr-bot[bot] via Run AWS Tests #8756
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants