Skip to content

Nixlbench: register remote IOVs only for storage backends - #1772

Merged
aranadive merged 1 commit into
ai-dynamo:mainfrom
iyastreb:iyastreb/nixlbench-remote-iovs-fix
Jun 15, 2026
Merged

aranadive merged 1 commit into
ai-dynamo:mainfrom
iyastreb:iyastreb/nixlbench-remote-iovs-fix

Conversation

@iyastreb

@iyastreb iyastreb commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

What?

Bugfix https://nvbugspro.nvidia.com/bug/6310482
Fix --reregister_mem failing for memory/network backends (e.g. UCX) with
"VRAM is detected as host by UCX".

Why?

registerIterationMem()/deregisterIterationMem() register the remote IOVs
locally on every iteration, unconditionally. For memory backends the remote side
is a peer process's memory (exchanged via metadata), not a local allocation, so
registering those peer addresses locally is invalid — UCX can't resolve them and
reports VRAM as host. The normal alloc/dealloc path only registers remote memory
for storage backends; the per-iteration path missed that gate. Regression from
#1474.

How?

Gate the remote register/deregister on isStorageBackend(), matching
allocateMemory()/deallocateMemory(). Memory backends now (de)register only
local memory per iteration, as before.

Summary by CodeRabbit

  • Bug Fixes
    • Optimized memory management for non-storage backends to only register local memory regions, reducing unnecessary remote operations.

@github-actions

Copy link
Copy Markdown

👋 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.

🚀

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

In nixl_worker.cpp, registerIterationMem and deregisterIterationMem now gate the remote agent->registerMem and agent->deregisterMem calls behind xferBenchConfig::isStorageBackend(). Local memory registration remains unconditional; remote registration is skipped for non-storage backends.

Changes

Conditional Remote Memory Registration

Layer / File(s) Summary
Conditional remote mem register/deregister
benchmark/nixlbench/src/worker/nixl/nixl_worker.cpp
Wraps remote agent->registerMem and agent->deregisterMem calls in xferBenchConfig::isStorageBackend() checks in both registerIterationMem and deregisterIterationMem; local registration is unchanged.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Possibly related PRs

  • ai-dynamo/nixl#1689: Modifies the same registerIterationMem/deregisterIterationMem functions in nixl_worker.cpp, refactoring how remote agent->registerMem/deregisterMem are built and executed.

Suggested reviewers

  • brminich
  • aranadive
  • ovidiusm

Poem

A rabbit hops through memory lanes,
Remote calls now wear storage chains,
Local regions always run free,
But remote ones wait for the backend key.
🐇 Only storage backends need apply! 🗄️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: conditional remote IOV registration limited to storage backends.
Description check ✅ Passed The description follows the template with complete What, Why, and How sections, providing clear context about the bugfix, root cause, and implementation approach.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
benchmark/nixlbench/src/worker/nixl/nixl_worker.cpp (1)

1347-1358: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix partial registration lifecycle to avoid leaked/inconsistent agent state on errors.

When storage remote registration fails after local registration succeeds, the function returns without rolling back local registration. Similarly, deregistration does local first, so a remote failure can leave remote state behind. This creates inconsistent state during --reregister_mem failure paths.

Suggested fix
 static nixl_status_t
 registerIterationMem(nixlAgent *agent,
                      const std::vector<xferBenchIOV> &local_iov,
                      const std::vector<xferBenchIOV> &remote_iov,
                      nixlBackendH *backend_engine) {
     nixl_opt_args_t reg_args;
     reg_args.backends.push_back(backend_engine);

     nixl_reg_dlist_t local_reg = iovListToNixlRegDlist(local_iov, GET_SEG_TYPE(true));
     nixl_status_t rc = agent->registerMem(local_reg, &reg_args);
     if (rc != NIXL_SUCCESS) {
         return rc;
     }

     if (xferBenchConfig::isStorageBackend()) {
         nixl_reg_dlist_t remote_reg = iovListToNixlRegDlist(remote_iov, getRemoteSegType());
         rc = agent->registerMem(remote_reg, &reg_args);
         if (rc != NIXL_SUCCESS) {
+            // Best-effort rollback to keep registration state consistent.
+            (void)agent->deregisterMem(local_reg, &reg_args);
             return rc;
         }
     }

     return NIXL_SUCCESS;
 }

 static nixl_status_t
 deregisterIterationMem(nixlAgent *agent,
                        const std::vector<xferBenchIOV> &local_iov,
                        const std::vector<xferBenchIOV> &remote_iov,
                        nixlBackendH *backend_engine) {
     nixl_opt_args_t reg_args;
     reg_args.backends.push_back(backend_engine);

-    nixl_reg_dlist_t local_reg = iovListToNixlRegDlist(local_iov, GET_SEG_TYPE(true));
-    nixl_status_t rc = agent->deregisterMem(local_reg, &reg_args);
-    if (rc != NIXL_SUCCESS) {
-        return rc;
-    }
+    nixl_status_t rc = NIXL_SUCCESS;

     if (xferBenchConfig::isStorageBackend()) {
         nixl_reg_dlist_t remote_reg = iovListToNixlRegDlist(remote_iov, getRemoteSegType());
         rc = agent->deregisterMem(remote_reg, &reg_args);
         if (rc != NIXL_SUCCESS) {
             return rc;
         }
     }
+
+    nixl_reg_dlist_t local_reg = iovListToNixlRegDlist(local_iov, GET_SEG_TYPE(true));
+    rc = agent->deregisterMem(local_reg, &reg_args);
+    if (rc != NIXL_SUCCESS) {
+        return rc;
+    }

     return NIXL_SUCCESS;
 }

Also applies to: 1373-1384

🤖 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 `@benchmark/nixlbench/src/worker/nixl/nixl_worker.cpp` around lines 1347 -
1358, The code has a partial registration lifecycle issue where if local memory
registration succeeds but remote registration fails (in the storage backend
path), the function returns without rolling back the local registration, leaving
inconsistent agent state. At benchmark/nixlbench/src/worker/nixl/nixl_worker.cpp
lines 1347-1358 (anchor), when the remote registerMem call for remote_reg fails
after local registration succeeds, add a deregistration call to rollback the
local_reg before returning the error code. The same fix pattern must be applied
at lines 1373-1384 (siblings) in the deregistration path, where if the remote
deregistration fails after local deregistration succeeds, you must handle the
error appropriately to prevent leaving remote state behind. Ensure error
handling maintains consistent agent state across all failure paths.
🤖 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 `@benchmark/nixlbench/src/worker/nixl/nixl_worker.cpp`:
- Around line 1347-1358: The code has a partial registration lifecycle issue
where if local memory registration succeeds but remote registration fails (in
the storage backend path), the function returns without rolling back the local
registration, leaving inconsistent agent state. At
benchmark/nixlbench/src/worker/nixl/nixl_worker.cpp lines 1347-1358 (anchor),
when the remote registerMem call for remote_reg fails after local registration
succeeds, add a deregistration call to rollback the local_reg before returning
the error code. The same fix pattern must be applied at lines 1373-1384
(siblings) in the deregistration path, where if the remote deregistration fails
after local deregistration succeeds, you must handle the error appropriately to
prevent leaving remote state behind. Ensure error handling maintains consistent
agent state across all failure paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: ef45e777-32c5-4b43-930b-9f22aae63065

📥 Commits

Reviewing files that changed from the base of the PR and between 03ea9a2 and 78e4f1e.

📒 Files selected for processing (1)
  • benchmark/nixlbench/src/worker/nixl/nixl_worker.cpp

@iyastreb

Copy link
Copy Markdown
Contributor Author

/build

@iyastreb
iyastreb requested a review from benlwalker June 15, 2026 14:18
@aranadive
aranadive merged commit c28061f into ai-dynamo:main Jun 15, 2026
17 checks passed
@iyastreb
iyastreb deleted the iyastreb/nixlbench-remote-iovs-fix branch June 16, 2026 04:19
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.

2 participants