Skip to content

Commit 57556bb

Browse files
committed
UCT/ROCM: initial commit for device initiated ipc put
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.
1 parent d9c844a commit 57556bb

22 files changed

Lines changed: 1189 additions & 120 deletions

config/hip.am

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#
2+
# Copyright (c) Advanced Micro Devices, Inc. 2026. ALL RIGHTS RESERVED.
3+
# See file LICENSE for terms.
4+
#
5+
6+
SUFFIXES = .hip
7+
8+
HIPCC ?= hipcc
9+
10+
HIPCC_CMD = $(HIPCC) $(DEFS) -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 $@
11+
HIPCC_LT_CMD = $(LIBTOOL) --tag=CXX --mode=compile $(HIPCC_CMD)
12+
13+
define hipcc-build
14+
@$(MKDIR_P) $(shell dirname $@) $(shell dirname $(DEPDIR)/hip/$@)
15+
@$(if $(filter false,$(AM_V_P)),echo " HIPCC $@")
16+
@$(if $(filter .o,$(suffix $@)),$(HIPCC_CMD),$(HIPCC_LT_CMD)) $($(1)) $(if $(filter false,$(AM_V_P)), >/dev/null)
17+
endef
18+
19+
define hipcc-source
20+
EXTRA_DIST += $(2)
21+
$(1): $(2)
22+
$$(call hipcc-build,$(3))
23+
endef
24+
25+
# Default rules when no target-specific compile flags are required
26+
.hip.o:
27+
$(call hipcc-build)
28+
29+
.hip.lo:
30+
$(call hipcc-build)
31+
32+
HIP_DEP_FILES := $(shell find $(DEPDIR)/hip/ -type f -name *.d 2>/dev/null)
33+
-include $(HIP_DEP_FILES)
34+
35+
clean-local:
36+
-rm -rf $(DEPDIR)/hip
37+
38+
distclean-local:
39+
-rm -rf $(DEPDIR)/hip

src/ucp/core/ucp_device.c

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2025-2026. ALL RIGHTS RESERVED.
3+
* Copyright (C) Advanced Micro Devices, Inc. 2026. ALL RIGHTS RESERVED.
34
*
45
* See file LICENSE for terms.
56
*/
@@ -106,8 +107,8 @@ static uct_allocated_memory_t ucp_device_mem_handle_hash_remove(void *handle)
106107
}
107108

108109
static ucs_status_t
109-
ucp_device_detect_local_sys_dev(ucp_context_h context,
110-
ucs_memory_type_t mem_type,
110+
ucp_device_detect_local_sys_dev(const ucp_context_h context,
111+
const ucs_memory_type_t mem_type,
111112
ucs_sys_device_t *local_sys_dev)
112113
{
113114
ucs_memory_info_t mem_info;
@@ -310,7 +311,7 @@ static ucs_status_t ucp_device_local_mem_list_create_handle(
310311

311312
static ucs_status_t ucp_device_local_mem_list_params_check(
312313
const ucp_device_mem_list_params_t *params, ucs_memory_type_t mem_type,
313-
ucs_sys_device_t *local_sys_dev)
314+
ucs_sys_device_t local_sys_dev)
314315
{
315316
const ucp_device_mem_list_elem_t *local_elements = UCS_PARAM_VALUE(
316317
UCP_DEVICE_MEM_LIST_PARAMS_FIELD, params, elements, ELEMENTS, NULL);
@@ -325,7 +326,6 @@ static ucs_status_t ucp_device_local_mem_list_params_check(
325326
const ucp_device_mem_list_elem_t *element;
326327
ucp_mem_h memh;
327328
size_t i;
328-
ucs_status_t status;
329329

330330
if ((local_elements == NULL) || (element_size == 0) ||
331331
(num_elements == 0) || (worker == NULL)) {
@@ -335,12 +335,6 @@ static ucs_status_t ucp_device_local_mem_list_params_check(
335335
return UCS_ERR_INVALID_PARAM;
336336
}
337337

338-
status = ucp_device_detect_local_sys_dev(worker->context, mem_type,
339-
local_sys_dev);
340-
if (status != UCS_OK) {
341-
return status;
342-
}
343-
344338
for (i = 0; i < num_elements; i++) {
345339
element = (const ucp_device_mem_list_elem_t*)
346340
UCS_PTR_BYTE_OFFSET(local_elements, i * element_size);
@@ -351,26 +345,59 @@ static ucs_status_t ucp_device_local_mem_list_params_check(
351345
return UCS_ERR_INVALID_PARAM;
352346
}
353347

354-
if (memh->sys_dev != *local_sys_dev) {
348+
if (memh->sys_dev != local_sys_dev) {
355349
ucs_error("mismatched local sys_dev for element=%zu", i);
356350
return UCS_ERR_UNSUPPORTED;
357351
}
358352
}
359353

354+
return UCS_OK;
355+
}
356+
357+
static ucs_status_t
358+
ucp_device_detect_export_mem_type(const ucp_context_h context,
359+
ucs_memory_type_t *export_mem_type_p,
360+
ucs_sys_device_t *sys_dev_p)
361+
{
362+
ucs_status_t status = UCS_ERR_UNSUPPORTED;
363+
ucs_memory_type_t mem_type;
364+
365+
ucs_for_each_bit(mem_type, UCP_DEVICE_MEM_TYPES) {
366+
status = ucp_device_detect_local_sys_dev(context, mem_type, sys_dev_p);
367+
if (status == UCS_OK) {
368+
*export_mem_type_p = mem_type;
369+
break;
370+
}
371+
}
372+
360373
return status;
361374
}
362375

363376
ucs_status_t
364377
ucp_device_local_mem_list_create(const ucp_device_mem_list_params_t *params,
365378
ucp_device_local_mem_list_h *mem_list_h)
366379
{
367-
const ucs_memory_type_t export_mem_type = UCS_MEMORY_TYPE_CUDA;
368-
ucs_status_t status;
369-
uct_allocated_memory_t mem;
380+
const ucp_worker_h worker = UCS_PARAM_VALUE(UCP_DEVICE_MEM_LIST_PARAMS_FIELD,
381+
params, worker, WORKER, NULL);
382+
ucs_memory_type_t export_mem_type;
370383
ucs_sys_device_t local_sys_dev;
384+
uct_allocated_memory_t mem;
385+
ucs_status_t status;
386+
387+
if (worker == NULL) {
388+
ucs_error("missing worker in local mem list params");
389+
return UCS_ERR_INVALID_PARAM;
390+
}
391+
392+
status = ucp_device_detect_export_mem_type(worker->context,
393+
&export_mem_type,
394+
&local_sys_dev);
395+
if (status != UCS_OK) {
396+
return status;
397+
}
371398

372399
status = ucp_device_local_mem_list_params_check(params, export_mem_type,
373-
&local_sys_dev);
400+
local_sys_dev);
374401
if (status != UCS_OK) {
375402
ucs_error("failed to check local mem list params: %s",
376403
ucs_status_string(status));
@@ -534,32 +561,20 @@ ucp_device_remote_mem_list_fill(const ucp_device_mem_list_elem_t *ucp_element,
534561
}
535562

536563
static ucs_status_t ucp_device_remote_mem_list_create_handle(
537-
const ucp_device_mem_list_params_t *params, ucs_memory_type_t mem_type,
538-
uct_allocated_memory_t *mem)
564+
const ucp_device_mem_list_params_t *params, const ucp_ep_h ep,
565+
const ucs_memory_type_t mem_type, uct_allocated_memory_t *mem,
566+
const ucs_sys_device_t local_sys_dev)
539567
{
540-
const ucp_ep_h ep = ucp_device_remote_mem_list_get_first_ep(params);
541568
size_t uct_elem_size;
542569
size_t handle_size = 0;
543570
ucp_tl_bitmap_t tl_bitmap[UCP_DEVICE_TL_TYPE_LAST] = {};
544571
const ucp_device_mem_list_elem_t *ucp_element;
545572
ucp_device_remote_mem_list_t *handle;
546573
uct_device_remote_mem_elem_t *uct_element;
547-
ucs_sys_device_t local_sys_dev;
548574
size_t i, num_lanes;
549575
ucs_status_t status;
550576
int tl_type;
551577

552-
if (ep == NULL) {
553-
ucs_error("no ep found in remote mem list");
554-
return UCS_ERR_INVALID_PARAM;
555-
}
556-
557-
status = ucp_device_detect_local_sys_dev(ep->worker->context, mem_type,
558-
&local_sys_dev);
559-
if (status != UCS_OK) {
560-
return status;
561-
}
562-
563578
ucp_device_get_tl_bitmap(ep->worker, tl_bitmap, local_sys_dev);
564579

565580
/* handle->num_lanes is the least common multiple of both lane types, so:
@@ -582,7 +597,7 @@ static ucs_status_t ucp_device_remote_mem_list_create_handle(
582597
uct_elem_size = sizeof(uct_device_remote_mem_elem_t) +
583598
(sizeof(uct_device_remote_tl_elem_t) * num_lanes);
584599
handle_size = sizeof(*handle) + (params->num_elements * uct_elem_size);
585-
handle = ucs_calloc(1, handle_size, "ucp_device_remote_mem_list_t");
600+
handle = ucs_calloc(1, handle_size, "ucp_device_remote_mem_list_t");
586601
if (handle == NULL) {
587602
ucs_error("failed to allocate ucp_device_remote_mem_list_t");
588603
return UCS_ERR_NO_MEMORY;
@@ -601,7 +616,7 @@ static ucs_status_t ucp_device_remote_mem_list_create_handle(
601616

602617
if (tl_type == UCP_DEVICE_TL_TYPE_LAST) {
603618
ucs_error("lane not found for element %zd", i);
604-
status = UCS_ERR_INVALID_PARAM;
619+
status = UCS_ERR_INVALID_PARAM;
605620
goto out;
606621
}
607622

@@ -616,10 +631,10 @@ static ucs_status_t ucp_device_remote_mem_list_create_handle(
616631
ucp_element = UCS_PTR_BYTE_OFFSET(ucp_element, params->element_size);
617632
}
618633

619-
handle->version = UCP_DEVICE_MEM_LIST_VERSION_V1;
620-
handle->length = params->num_elements;
634+
handle->version = UCP_DEVICE_MEM_LIST_VERSION_V1;
635+
handle->length = params->num_elements;
621636
handle->num_lanes = num_lanes;
622-
status = ucp_device_mem_list_export_handle(
637+
status = ucp_device_mem_list_export_handle(
623638
ep->worker, handle, handle_size, mem_type, local_sys_dev, mem,
624639
"ucp_device_remote_mem_list_handle_t");
625640

@@ -683,17 +698,31 @@ ucs_status_t
683698
ucp_device_remote_mem_list_create(const ucp_device_mem_list_params_t *params,
684699
ucp_device_remote_mem_list_h *mem_list_h)
685700
{
686-
const ucs_memory_type_t export_mem_type = UCS_MEMORY_TYPE_CUDA;
687-
ucs_status_t status;
701+
const ucp_ep_h ep = ucp_device_remote_mem_list_get_first_ep(params);
702+
ucs_memory_type_t export_mem_type;
703+
ucs_sys_device_t sys_dev;
688704
uct_allocated_memory_t mem;
705+
ucs_status_t status;
706+
707+
if (ep == NULL) {
708+
ucs_error("no ep found in remote mem list params");
709+
return UCS_ERR_INVALID_PARAM;
710+
}
711+
712+
status = ucp_device_detect_export_mem_type(ep->worker->context,
713+
&export_mem_type, &sys_dev);
714+
if (status != UCS_OK) {
715+
return status;
716+
}
689717

690718
status = ucp_device_remote_mem_list_params_check(params);
691719
if (status != UCS_OK) {
692720
return status;
693721
}
694722

695-
status = ucp_device_remote_mem_list_create_handle(params, export_mem_type,
696-
&mem);
723+
status = ucp_device_remote_mem_list_create_handle(params, ep,
724+
export_mem_type,
725+
&mem, sys_dev);
697726
if (status != UCS_OK) {
698727
/*
699728
* Do not log error for UCS_ERR_NOT_CONNECTED because it is expected

src/ucp/core/ucp_mm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,5 +281,7 @@ static UCS_F_ALWAYS_INLINE size_t ucp_memh_length(const ucp_mem_h memh)
281281
UCS_BIT(UCS_MEMORY_TYPE_ROCM) | \
282282
UCS_BIT(UCS_MEMORY_TYPE_ZE_DEVICE) | \
283283
UCS_BIT(UCS_MEMORY_TYPE_ZE_MANAGED)))
284+
#define UCP_DEVICE_MEM_TYPES \
285+
(UCS_BIT(UCS_MEMORY_TYPE_CUDA) | UCS_BIT(UCS_MEMORY_TYPE_ROCM))
284286

285287
#endif

src/ucp/wireup/select.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
* Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2001-2026. ALL RIGHTS RESERVED.
33
* Copyright (C) Los Alamos National Security, LLC. 2019 ALL RIGHTS RESERVED.
4+
* Copyright (C) Advanced Micro Devices, Inc. 2026. ALL RIGHTS RESERVED.
45
*
56
* See file LICENSE for terms.
67
*/
@@ -2620,7 +2621,8 @@ ucp_wireup_add_device_lanes(const ucp_wireup_select_params_t *select_params,
26202621
ucp_wireup_select_bw_info_t bw_info = {};
26212622
const uint64_t mem_type_bitmaps[] = {UCS_BIT(UCS_MEMORY_TYPE_CUDA),
26222623
UCS_BIT(UCS_MEMORY_TYPE_CUDA) |
2623-
UCS_BIT(UCS_MEMORY_TYPE_HOST)};
2624+
UCS_BIT(UCS_MEMORY_TYPE_HOST),
2625+
UCS_BIT(UCS_MEMORY_TYPE_ROCM)};
26242626
int found_lane = 0;
26252627
size_t i;
26262628
ucp_tl_bitmap_t mem_type_tl_bitmap;

src/ucs/sys/device_code.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2025. ALL RIGHTS RESERVED.
3+
* Copyright (C) Advanced Micro Devices, Inc. 2026. ALL RIGHTS RESERVED.
34
*
45
* See file LICENSE for terms.
56
*/
@@ -13,11 +14,11 @@
1314
/*
1415
* Declare GPU specific functions
1516
*/
16-
#ifdef __NVCC__
17+
#if defined(__NVCC__) || defined(__HIPCC__)
1718
#define UCS_F_DEVICE __device__ __forceinline__ static
1819
#else
1920
#define UCS_F_DEVICE static inline
20-
#endif /* __NVCC__ */
21+
#endif /* __NVCC__ || __HIPCC__ */
2122

2223

2324
#ifndef UCP_DEVICE_ENABLE_PARAMS_CHECK
@@ -32,6 +33,9 @@
3233
/* Number of threads in a warp */
3334
#define UCS_DEVICE_NUM_THREADS_IN_WARP 32
3435

36+
/* Check if _n is aligned to a power-of-2 boundary _p */
37+
#define UCS_DEVICE_IS_ALIGNED_POW2(_n, _p) (!((_n) & ((_p) - 1)))
38+
3539

3640
/* nvcc does not provide __builtin_ia32_prefetch used by GCC's x86 intrinsic headers.
3741
Redirect to the generic __builtin_prefetch so those headers compile. */

src/uct/api/device/uct_device_impl.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2025-2026. ALL RIGHTS RESERVED.
3+
* Copyright (C) Advanced Micro Devices, Inc. 2026. ALL RIGHTS RESERVED.
34
*
45
* See file LICENSE for terms.
56
*/
@@ -20,6 +21,14 @@
2021
#define UCT_CUDA_IPC_SUPPORTED 0
2122
#endif
2223

24+
#if (defined(HAVE_ROCM) || \
25+
(!defined(HAVE_CONFIG_H) && __has_include(<uct/rocm/ipc/rocm_ipc.h>)))
26+
#include <uct/rocm/ipc/rocm_ipc.h>
27+
#define UCT_ROCM_IPC_SUPPORTED 1
28+
#else
29+
#define UCT_ROCM_IPC_SUPPORTED 0
30+
#endif
31+
2332
#if (defined(HAVE_GDA) || \
2433
(!defined(HAVE_CONFIG_H) && \
2534
__has_include(<uct/ib/mlx5/gdaki/gdaki.cuh>) && \
@@ -30,8 +39,10 @@
3039
#define UCT_RC_MLX5_GDA_SUPPORTED 0
3140
#endif
3241

33-
#if __has_include(<uct/ib/mlx5/gdaki/d2p.cuh>) && \
34-
__has_include(<infiniband/mlx5dv.h>)
42+
#if (defined(HAVE_GDA) || \
43+
(!defined(HAVE_CONFIG_H) && \
44+
__has_include(<uct/ib/mlx5/gdaki/d2p.cuh>) && \
45+
__has_include(<infiniband/mlx5dv.h>)))
3546
#include <uct/ib/mlx5/gdaki/d2p.cuh>
3647
#define UCT_D2P_SUPPORTED 1
3748
#else
@@ -45,6 +56,9 @@ union uct_device_completion {
4556
#if UCT_CUDA_IPC_SUPPORTED
4657
uct_cuda_ipc_completion_t cuda_ipc;
4758
#endif
59+
#if UCT_ROCM_IPC_SUPPORTED
60+
uct_rocm_ipc_completion_t rocm_ipc;
61+
#endif
4862
};
4963

5064

@@ -105,6 +119,12 @@ UCS_F_DEVICE ucs_status_t uct_device_ep_put(
105119
channel_id, flags, comp);
106120
}
107121
#endif
122+
#if UCT_ROCM_IPC_SUPPORTED
123+
if (device_ep->uct_tl_id == UCT_DEVICE_TL_ROCM_IPC) {
124+
return uct_rocm_ipc_ep_put<level>(device_ep, mem_elem, address,
125+
remote_address, length, flags, comp);
126+
}
127+
#endif
108128

109129
return UCS_ERR_UNSUPPORTED;
110130
}
@@ -163,6 +183,12 @@ UCS_F_DEVICE ucs_status_t uct_device_ep_atomic_add(
163183
flags, comp);
164184
}
165185
#endif
186+
#if UCT_ROCM_IPC_SUPPORTED
187+
if (device_ep->uct_tl_id == UCT_DEVICE_TL_ROCM_IPC) {
188+
return uct_rocm_ipc_ep_atomic_add<level>(device_ep, mem_elem, inc_value,
189+
remote_address, flags, comp);
190+
}
191+
#endif
166192

167193
return UCS_ERR_UNSUPPORTED;
168194
}
@@ -191,6 +217,11 @@ UCS_F_DEVICE ucs_status_t uct_device_ep_get_ptr(
191217
return uct_cuda_ipc_ep_get_ptr(device_ep, mem_elem, address, addr_p);
192218
}
193219
#endif
220+
#if UCT_ROCM_IPC_SUPPORTED
221+
if (device_ep->uct_tl_id == UCT_DEVICE_TL_ROCM_IPC) {
222+
return uct_rocm_ipc_ep_get_ptr(device_ep, mem_elem, address, addr_p);
223+
}
224+
#endif
194225

195226
return UCS_ERR_UNSUPPORTED;
196227
}

0 commit comments

Comments
 (0)