Skip to content

UCT/ROCM: initial commit for device initiated ipc put - #11299

Merged
ofirfarjun7 merged 1 commit into
openucx:masterfrom
mshanthagit:pr/device-init-put
Aug 7, 2026
Merged

UCT/ROCM: initial commit for device initiated ipc put#11299
ofirfarjun7 merged 1 commit into
openucx:masterfrom
mshanthagit:pr/device-init-put

Conversation

@mshanthagit

@mshanthagit mshanthagit commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

What?

This PR introduces device initiated IPC put operation for the rocm component.

Why?

It is a new functionality to enable device initiated communication.

How?

It is optional, but for complex PRs, please provide information about the design,
architecture, approach, etc.

@mshanthagit
mshanthagit marked this pull request as draft March 27, 2026 15:54
@mshanthagit
mshanthagit force-pushed the pr/device-init-put branch 2 times, most recently from ee24de0 to 67b5b78 Compare March 30, 2026 18:28
@mshanthagit
mshanthagit marked this pull request as ready for review April 8, 2026 12:58
@mshanthagit

Copy link
Copy Markdown
Contributor Author

This PR is now ready for review.

Comment thread src/ucp/core/ucp_device.c Outdated
@openucx openucx deleted a comment from svc-nixl May 4, 2026
Comment thread src/ucp/core/ucp_device.c
Comment thread src/ucp/core/ucp_device.c Outdated
Comment thread src/ucp/core/ucp_device.c Outdated
Comment thread src/ucp/wireup/select.c Outdated
Comment thread src/uct/api/device/uct_device_impl.h Outdated

@mshanthagit mshanthagit left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@ofirfarjun7 addressed your comments.

Comment thread src/uct/api/device/uct_device_impl.h Outdated
Comment thread src/ucp/wireup/select.c Outdated
Comment thread src/ucp/core/ucp_device.c Outdated
Comment thread src/ucp/wireup/select.c Outdated
ucp_context_h context = select_params->ep->worker->context;
unsigned ep_init_flags = ucp_wireup_ep_init_flags(select_params,
select_ctx);
static const ucs_memory_type_t device_mem_types[] = {

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.

maybe add const UCP_MEMORY_TYPES_DEVICE
(UCS_BIT(UCS_MEMORY_TYPE_CUDA) | UCS_BIT(UCS_MEMORY_TYPE_ROCM)
and use ucs_memory_type_for_each to iterate skiping non-DEVICE memtypes, here and in ucp_device_detect_export_mem_type

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

addressed this comment. added a #define in ucp_mm.h and used ucs_for_each_bit(mem_type, UCP_DEVICE_MEM_TYPES) within the files.

Comment thread src/ucp/core/ucp_device.c Outdated
return status;
}

status = ucp_device_remote_mem_list_create_handle(params, export_mem_type,

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.

pass first ep so it won't need to look again

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ack

Comment thread src/ucp/core/ucp_device.c Outdated
ucs_status_t status;
uct_allocated_memory_t mem;
ucs_sys_device_t sys_dev;
ucp_ep_h ep = ucp_device_remote_mem_list_get_first_ep(params);

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.

initialized vars first

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ack.

Comment thread src/uct/rocm/ipc/rocm_ipc_md.c Outdated
}

uct_rocm_ipc_component_t uct_rocm_ipc_component = {
.super = {.query_md_resources = uct_rocm_base_query_md_resources,

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.

strange code format

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

formatted it.

@mshanthagit mshanthagit left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@Artemy-Mellanox incorporated your suggestions in the latest commit.

Comment thread src/uct/rocm/ipc/rocm_ipc_md.c Outdated
}

uct_rocm_ipc_component_t uct_rocm_ipc_component = {
.super = {.query_md_resources = uct_rocm_base_query_md_resources,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

formatted it.

Comment thread src/ucp/wireup/select.c Outdated
ucp_context_h context = select_params->ep->worker->context;
unsigned ep_init_flags = ucp_wireup_ep_init_flags(select_params,
select_ctx);
static const ucs_memory_type_t device_mem_types[] = {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

addressed this comment. added a #define in ucp_mm.h and used ucs_for_each_bit(mem_type, UCP_DEVICE_MEM_TYPES) within the files.

Comment thread src/ucp/core/ucp_device.c Outdated
ucs_status_t status;
uct_allocated_memory_t mem;
ucs_sys_device_t sys_dev;
ucp_ep_h ep = ucp_device_remote_mem_list_get_first_ep(params);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ack.

Comment thread src/ucp/core/ucp_device.c Outdated
return status;
}

status = ucp_device_remote_mem_list_create_handle(params, export_mem_type,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ack

@mshanthagit

Copy link
Copy Markdown
Contributor Author

@Artemy-Mellanox did you get a chance to review the changes?

@edgargabriel

Copy link
Copy Markdown
Contributor

I just wanted to add a comment here that I know that I am listed as reviewer and I am happy to sign off on the PR. @mshanthagit and me have discussed the issue and the actual ticket internally multiple times, so I am very well aware of the technical aspects of it.

@mshanthagit
mshanthagit force-pushed the pr/device-init-put branch from 927735e to b8832e5 Compare May 18, 2026 02:24
Comment thread src/ucp/core/ucp_device.c Outdated
Comment thread src/ucp/core/ucp_device.c
Comment thread src/ucp/core/ucp_device.c
Comment thread src/ucp/core/ucp_device.c Outdated
Comment thread src/uct/rocm/ipc/rocm_ipc.h Outdated
Comment thread src/uct/rocm/ipc/rocm_ipc_cache.c
Comment thread src/uct/rocm/ipc/rocm_ipc_ep.c
Comment thread src/uct/rocm/ipc/rocm_ipc_ep.c Outdated
Comment thread src/uct/rocm/ipc/rocm_ipc_ep.c
Comment thread src/uct/rocm/ipc/rocm_ipc_iface.c Outdated
@mshanthagit

Copy link
Copy Markdown
Contributor Author

@ofirfarjun7 addressed your comments except the one related to "UCT_CUDA_IPC_IS_ALIGNED_POW2". Can we move it to ucs/sys/device_code.h and name it as UCT_IPC_IS_ALIGNED_POW2?

@mshanthagit
mshanthagit force-pushed the pr/device-init-put branch from bdbf299 to a5c4b47 Compare June 2, 2026 16:03
@mshanthagit

Copy link
Copy Markdown
Contributor Author

@ofirfarjun7 rebased and addressed all comments.

Comment thread src/ucp/core/ucp_device.c Outdated
Comment thread src/ucp/core/ucp_device.c Outdated
Comment thread src/ucs/sys/device_code.h Outdated
#define UCS_DEVICE_NUM_THREADS_IN_WARP 32

/* Check if _n is aligned to a power-of-2 boundary _p */
#define UCT_IPC_IS_ALIGNED_POW2(_n, _p) (!((_n) & ((_p) - 1)))

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.

maybe UCS_DEVICE_IS_ALIGNED_POW2?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

makes sense, my bad.

Comment thread config/hip.am Outdated

HIPCC ?= hipcc

HIPCC_CMD = $(HIPCC) -DHAVE_CONFIG_H -DUCT_DEVICE_CODE_HIP -fPIE -I$(top_srcdir)/src -I$(top_builddir)/src $(BASE_CXXFLAGS) $(CXXFLAGS) $(HIP_CPPFLAGS) $(HIP_CXXFLAGS) $(HIPCC_EXTRA_FLAGS) -Wno-c++20-extensions -c $< -MT $@ -MF $(DEPDIR)/hip/$@.d -MMD -o $@

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.

better $(DEFS) for -DHAVE_CONFIG_H

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ack

Comment thread src/ucp/core/ucp_device.c Outdated
ucs_status_t status;
uct_allocated_memory_t mem;
const ucp_worker_h worker = UCS_PARAM_VALUE(UCP_DEVICE_MEM_LIST_PARAMS_FIELD,
params, worker, WORKER, NULL);

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.

align

Comment thread src/uct/rocm/ipc/rocm_ipc_cache.c Outdated
if (status != UCS_OK) {
ucs_error("Failed to create ROCm IPC component cache: %s",
ucs_status_string(status));
pthread_mutex_unlock(&uct_rocm_ipc_component.lock);

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.

where is it locked? isn't it leftover?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, missed cleaning it up.

Comment thread src/uct/rocm/ipc/rocm_ipc_cache.c Outdated
ucs_status_t status;

UCS_INIT_ONCE(&cache_init_once) {
if (uct_rocm_ipc_component.ipc_cache == NULL) {

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.

isn't UCS_INIT_ONCE already do this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ack

Comment thread src/uct/rocm/ipc/rocm_ipc_iface.c
Comment thread src/uct/rocm/ipc/rocm_ipc.h Outdated
UCS_DEVICE_IS_ALIGNED_POW2((intptr_t)d1, sizeof(vec4))) {
const vec4 *s4 = reinterpret_cast<const vec4*>(s1);
vec4 *d4 = reinterpret_cast<vec4*>(d1);
size_t n4 = len / sizeof(vec4);

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.

n4 is num_lines in block, what's diff?
why warp/block should have separate implementations?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

merged the implementations.

Comment thread src/uct/rocm/ipc/rocm_ipc.h Outdated

/* System-wide atomic increment */
__device__ static inline void
uct_rocm_ipc_atomic_inc(uint64_t *dst, uint64_t inc_value)

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.

I'd call it atomic_add

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ack


#define UCS_DEVICE_LEVEL_EXEC_ID 1

#define UCS_DEVICE_LEVEL_EXEC_SELECT(scope_ok, count, id) \

@Artemy-Mellanox Artemy-Mellanox Jun 24, 2026

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.

couldn't it be static __device__ function?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

{
unsigned int thread_id = threadIdx.x;
unsigned int num_threads = blockDim.x;
unsigned int warp_id = thread_id / 64; // ROCm wavefront size

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.

why not use UCT_ROCM_IPC_WAVEFRONT_SIZE ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ack

Comment thread test/gtest/Makefile.am
if HAVE_GNUXX11
HIPCC_EXTRA_FLAGS = \
$(HIP_CPPFLAGS) \
-DHAVE_ROCM=1 \

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.

why not use __HIPCC__?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

ofirfarjun7
ofirfarjun7 previously approved these changes Jun 24, 2026
Comment thread test/gtest/uct/rocm/test_rocm_ipc_device.hip
@mshanthagit

Copy link
Copy Markdown
Contributor Author

@ofirfarjun7 @Artemy-Mellanox if the changes are satisfactory and the PR is ready to be merged, I would first like to squash the commits with an appropriate commit message and force push it (unless it allows me to squash it online).

@ofirfarjun7

Copy link
Copy Markdown
Contributor

@mshanthagit please fix all issues that cause CI to fail.
Please check https://github.com/openucx/ucx/wiki/Guidance-for-contributors

@mshanthagit

Copy link
Copy Markdown
Contributor Author

@mshanthagit please fix all issues that cause CI to fail. Please check https://github.com/openucx/ucx/wiki/Guidance-for-contributors

@ofirfarjun7 looks like the CI issues are related to "docker pull" failures. Please let me know if I missed anything obvious.

@mshanthagit

Copy link
Copy Markdown
Contributor Author

@ofirfarjun7 @Artemy-Mellanox I have rebased and there are no conflicts. There seems to be a failure, but I suspect it is not related to this PR. Please let me know if there's anything else blocking the approval. As noted earlier, I would like to squash the PR into a single commit, shall I do that now?

Comment thread src/uct/rocm/ipc/rocm_ipc.h
Comment thread src/uct/rocm/ipc/rocm_ipc.h
Comment thread src/uct/api/device/uct_device_impl.h Outdated
Comment thread src/uct/rocm/ipc/rocm_ipc_cache.c Outdated
self->remote_pid = *(const pid_t*)params->iface_addr;

snprintf(target_name, sizeof(target_name), "dest:%d", *(pid_t*)params->iface_addr);
status = uct_rocm_ipc_create_cache(&self->remote_memh_cache, target_name);

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.

Can it create issues if cache is not private for each EP and lookup criteria is only remote VA?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In addition to the remote VA, ipc handles are compared as well to avoid conflicts. Do you foresee any issues with this appoach?

@ofirfarjun7 ofirfarjun7 Aug 4, 2026

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.

But if ipc handles are not the same you remove it from the cache because it is "stale region".
But what if two remote processes has two regions with same VA?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In that case, we might see a ping-pong of effect that may impact performance, as the process has to now go though hsa_amd_ipc_memory_attach instead of using cached entry.

@ofirfarjun7 ofirfarjun7 Aug 4, 2026

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.

Maybe add another dimension to the key? You can examine cuda ipc cache.
If you think it will just impact performance and you prefer to leave it as is let me know.

@ofirfarjun7
ofirfarjun7 requested a review from rakhmets July 30, 2026 06:56
@edgargabriel

Copy link
Copy Markdown
Contributor

Could we try to get this PR over the finish line and have it merged? It has been opened on March 15, so its now nearly five months that it is pending.

Comment thread src/uct/api/device/uct_device_impl.h
self->remote_pid = *(const pid_t*)params->iface_addr;

snprintf(target_name, sizeof(target_name), "dest:%d", *(pid_t*)params->iface_addr);
status = uct_rocm_ipc_create_cache(&self->remote_memh_cache, target_name);

@ofirfarjun7 ofirfarjun7 Aug 4, 2026

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.

But if ipc handles are not the same you remove it from the cache because it is "stale region".
But what if two remote processes has two regions with same VA?

@ofirfarjun7

Copy link
Copy Markdown
Contributor

Could we try to get this PR over the finish line and have it merged? It has been opened on March 15, so its now nearly five months that it is pending.

If these two are not a concern from your point of view let us know and we will finish the review
Can't disable cache for device:
https://github.com/openucx/ucx/pull/11299/changes/BASE..4dddf15e46735555405bf678be778a23358ec45f#r3466948308

Potential performance issue:
#11299 (comment)

@anjoj0

anjoj0 commented Aug 6, 2026

Copy link
Copy Markdown

@edgargabriel @mshanthagit Cross-linking the W7900 compatibility result from ai-dynamo/nixl#2039.

I tested #11299 head 4dddf15e4 plus only UCT_IFACE_FLAG_ERRHANDLE_PEER_FAILURE. The branch built successfully; the PR's ROCm IPC tests reported 92 passed / 40 expected skipped / 0 failed. NIXL default peer mode selected rocm_ipc/rocm_ipc at 27.377/23.527 GB/s (same NUMA) and 27.391/23.522 GB/s (cross NUMA), with verified payloads. Twelve legal cross-NUMA peer-exit injections returned verified completion or NIXL_ERR_REMOTE_DISCONNECT without a hang.

No handle-cache or device-initiated PUT code was changed. Full methods and hashes:
https://github.com/anjoj0/vllm-awq4-qwen-1.0/blob/main/w7900_optimization/results/20260806_ucx_pr11299_compatibility_report.md

Would you prefer the capability flag and a multi-process peer-exit regression to be absorbed into this PR, or handled as a small dependent follow-up?

@edgargabriel

Copy link
Copy Markdown
Contributor

Could we try to get this PR over the finish line and have it merged? It has been opened on March 15, so its now nearly five months that it is pending.

If these two are not a concern from your point of view let us know and we will finish the review Can't disable cache for device: https://github.com/openucx/ucx/pull/11299/changes/BASE..4dddf15e46735555405bf678be778a23358ec45f#r3466948308

Potential performance issue: #11299 (comment)

@ofirfarjun7 thank you, those things are a concern for us, and we discussed this with @mshanthagit internally. We think the most efficient way forward would be to merge this PR with a clear understanding of the shortcomings. The host-path is from the correctness perspective not affected (so we do not introduce a regression). There is potential for a performance regression in certain scenarios. However, because this is a massive PR we think its better to get it merged and fix the caching issue in a subsequent PR (which might come as soon as next week). The follow-up PR would only touch rocm_ipc and would have no impact on the rest of the UCX code base.

With this current PR, we are constantly rebasing to pull in updates to the repo, and had to resolve a number of conflicts over the weeks, its one of the reasons we would see benefits in merging this PR and fix the problems in a follow-up PR.

Introduces device initiated IPC put operation for the ROCm component.

- Add device-side rocm_ipc.h with HIP __device__ put/atomic_add/get_ptr,
  including a strided int4/int2 vectorized copy at thread/warp/block levels.
- Add MD mem_elem_pack/rkey_ptr that map the remote IPC handle via a shared,
  lazily-initialized process-wide handle cache; iface/ep now expose a device ep.
@ofirfarjun7
ofirfarjun7 merged commit 0957aae into openucx:master Aug 7, 2026
161 checks passed
@ofirfarjun7

Copy link
Copy Markdown
Contributor

Could we try to get this PR over the finish line and have it merged? It has been opened on March 15, so its now nearly five months that it is pending.

If these two are not a concern from your point of view let us know and we will finish the review Can't disable cache for device: https://github.com/openucx/ucx/pull/11299/changes/BASE..4dddf15e46735555405bf678be778a23358ec45f#r3466948308
Potential performance issue: #11299 (comment)

@ofirfarjun7 thank you, those things are a concern for us, and we discussed this with @mshanthagit internally. We think the most efficient way forward would be to merge this PR with a clear understanding of the shortcomings. The host-path is from the correctness perspective not affected (so we do not introduce a regression). There is potential for a performance regression in certain scenarios. However, because this is a massive PR we think its better to get it merged and fix the caching issue in a subsequent PR (which might come as soon as next week). The follow-up PR would only touch rocm_ipc and would have no impact on the rest of the UCX code base.

With this current PR, we are constantly rebasing to pull in updates to the repo, and had to resolve a number of conflicts over the weeks, its one of the reasons we would see benefits in merging this PR and fix the problems in a follow-up PR.

I merged so you can progress.

Comment thread src/ucp/core/ucp_device.c
static ucs_status_t
ucp_device_detect_local_sys_dev(ucp_context_h context,
ucs_memory_type_t mem_type,
ucp_device_detect_local_sys_dev(const ucp_context_h context,

@rakhmets rakhmets Aug 7, 2026

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.

Please remove this const. Since it's typedef struct ucp_context *ucp_context_h, it does not work as readers might expect.

Comment thread src/ucp/core/ucp_device.c
Comment on lines +387 to +390
if (worker == NULL) {
ucs_error("missing worker in local mem list params");
return UCS_ERR_INVALID_PARAM;
}

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.

Please refactor this to avoid checking this parameter twice.

Comment thread src/ucp/core/ucp_device.c
Comment on lines +565 to +566
const ucs_memory_type_t mem_type, uct_allocated_memory_t *mem,
const ucs_sys_device_t local_sys_dev)

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.

Please swap the last two parameters, so that all input parameters go before the output.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rakhmets please review #11757, your comments are addressed there.

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