Skip to content

Commit 2e8426a

Browse files
committed
UCT/ROCM: Enable dmabuf by default with peermem fallback Use dma-buf for GPU-direct when the kernel supports it, and keep peermem as the fallback on older kernels. Also report allocation-base offsets for interior ROCm addresses.
1 parent d5b6b27 commit 2e8426a

6 files changed

Lines changed: 99 additions & 38 deletions

File tree

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Changcheng Liu <jerrliu@nvidia.com>
2424
Colin Hirsch <chirsch@nvidia.com>
2525
Corey J. Nolet <cjnolet@gmail.com>
2626
Daniel Pressler <danielpr@nvidia.com>
27+
David DeBonis <ddebonis@amd.com>
2728
David Wootton <dwootton@us.ibm.com>
2829
Devendar Bureddy <devendar@mellanox.com>
2930
Devesh Sharma <devesh.sharma@broadcom.com>

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@
99

1010
## Current
1111
### Features:
12+
#### ROCM
13+
* Enabled dmabuf by default for GPU-direct transfers, falling back to peermem when unavailable
1214
#### RDMA CORE (IB, ROCE, etc.)
1315
* UCX_IB_PCI_RELAXED_ORDERING=yes now requires all memory keys to use relaxed ordering and omits strict-order companion keys; the former "only" value is removed
1416
### Bugfixes:
17+
#### ROCM
18+
* Fixed dmabuf base address and offset for interior ROCm pointers
1519

1620
## 1.22.0 (August 2, 2026)
1721
### Features:

src/uct/rocm/base/rocm_base.c

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212

1313
#include <ucs/sys/string.h>
1414
#include <ucs/sys/module.h>
15+
#include <ucs/sys/sock.h>
1516
#include <ucs/memory/memtype_cache.h>
17+
#include <ucs/type/init_once.h>
1618
#include <sys/utsname.h>
1719
#include <pthread.h>
1820

@@ -333,9 +335,8 @@ FILE* uct_rocm_base_load_kernel_config_file()
333335

334336
int uct_rocm_base_file_contains_dmabuf_support(FILE* fp, const char kernel_opt1[], const char kernel_opt2[])
335337
{
336-
int dmabuf_supported = 0;
337-
int found_opt1 = 0;
338-
int found_opt2 = 0;
338+
int found_opt1 = 0;
339+
int found_opt2 = 0;
339340
char buf[256];
340341

341342
while (fgets(buf, sizeof(buf), fp) != NULL) {
@@ -346,10 +347,10 @@ int uct_rocm_base_file_contains_dmabuf_support(FILE* fp, const char kernel_opt1[
346347
found_opt2 = 1;
347348
}
348349
if (found_opt1 && found_opt2) {
349-
dmabuf_supported = 1;
350+
return 1;
350351
}
351352
}
352-
return dmabuf_supported;
353+
return 0;
353354
}
354355

355356
int uct_rocm_base_kernel_config_supports_dmabuf()
@@ -388,16 +389,24 @@ int uct_rocm_base_kernel_symbols_supports_dmabuf()
388389

389390
int uct_rocm_base_is_dmabuf_supported()
390391
{
391-
#if HAVE_HSA_AMD_PORTABLE_EXPORT_DMABUF
392-
if (uct_rocm_base_kernel_config_supports_dmabuf()) {
393-
return 1;
394-
}
392+
static ucs_init_once_t init_once = UCS_INIT_ONCE_INITIALIZER;
393+
static int dmabuf_supported = 0;
395394

396-
ucs_trace("no kernel conf file found or no support for dmabuf found, trying /proc/kallsyms fallback");
397-
return uct_rocm_base_kernel_symbols_supports_dmabuf();
398-
#else
399-
return 0;
395+
UCS_INIT_ONCE(&init_once) {
396+
#if HAVE_HSA_AMD_PORTABLE_EXPORT_DMABUF
397+
if (uct_rocm_base_kernel_config_supports_dmabuf()) {
398+
dmabuf_supported = 1;
399+
} else {
400+
ucs_trace("no kernel conf file found or no support for dmabuf "
401+
"found, trying /proc/kallsyms fallback");
402+
dmabuf_supported = uct_rocm_base_kernel_symbols_supports_dmabuf();
403+
}
400404
#endif
405+
ucs_debug("dmabuf is%s supported on ROCm",
406+
dmabuf_supported ? "" : " not");
407+
}
408+
409+
return dmabuf_supported;
401410
}
402411

403412
static void uct_rocm_base_dmabuf_export(const void *addr, const size_t length,
@@ -414,8 +423,8 @@ static void uct_rocm_base_dmabuf_export(const void *addr, const size_t length,
414423
if (status != HSA_STATUS_SUCCESS) {
415424
fd = UCT_DMABUF_FD_INVALID;
416425
offset = 0;
417-
ucs_warn("failed to export dmabuf handle for addr %p / %zu", addr,
418-
length);
426+
ucs_debug("failed to export dmabuf handle for addr %p / %zu: 0x%x",
427+
addr, length, status);
419428
}
420429

421430
ucs_trace("dmabuf export addr %p %lu to dmabuf fd %d offset %zu\n",
@@ -427,14 +436,13 @@ static void uct_rocm_base_dmabuf_export(const void *addr, const size_t length,
427436
}
428437

429438
ucs_status_t uct_rocm_base_mem_query(uct_md_h md, const void *addr,
430-
const size_t length,
439+
size_t length, int have_dmabuf,
431440
uct_md_mem_attr_v2_t *mem_attr_p)
432441
{
433442
size_t dmabuf_offset = 0;
434-
int is_exported = 0;
435443
ucs_memory_type_t mem_type = UCS_MEMORY_TYPE_HOST;
436444
ucs_sys_device_t sys_dev = UCS_SYS_DEVICE_ID_UNKNOWN;
437-
int dmabuf_fd;
445+
int dmabuf_fd = UCT_DMABUF_FD_INVALID;
438446
hsa_status_t status;
439447
hsa_device_type_t dev_type;
440448
hsa_amd_pointer_type_t hsa_mem_type;
@@ -447,7 +455,7 @@ ucs_status_t uct_rocm_base_mem_query(uct_md_h md, const void *addr,
447455
&base_size, &hsa_mem_type, &agent,
448456
&dev_type);
449457
if (status != HSA_STATUS_SUCCESS) {
450-
return status;
458+
return UCS_ERR_INVALID_ADDR;
451459
}
452460

453461
if ((hsa_mem_type == HSA_EXT_POINTER_TYPE_HSA) &&
@@ -458,6 +466,9 @@ ucs_status_t uct_rocm_base_mem_query(uct_md_h md, const void *addr,
458466
if (ucs_status != UCS_OK) {
459467
sys_dev = UCS_SYS_DEVICE_ID_UNKNOWN;
460468
}
469+
} else {
470+
base_addr = (void*)addr;
471+
base_size = length;
461472
}
462473

463474
if (mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_MEM_TYPE) {
@@ -469,26 +480,30 @@ ucs_status_t uct_rocm_base_mem_query(uct_md_h md, const void *addr,
469480
}
470481

471482
if (mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_BASE_ADDRESS) {
472-
mem_attr_p->base_address = (void*) addr;
483+
mem_attr_p->base_address = base_addr;
473484
}
474485

475486
if (mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_ALLOC_LENGTH) {
476-
mem_attr_p->alloc_length = length;
487+
mem_attr_p->alloc_length = base_size;
477488
}
478489

479-
if (mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_DMABUF_FD) {
480-
uct_rocm_base_dmabuf_export(addr, length, mem_type, &dmabuf_fd,
481-
&dmabuf_offset);
482-
mem_attr_p->dmabuf_fd = dmabuf_fd;
483-
is_exported = 1;
484-
}
490+
if ((mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_DMABUF_FD) ||
491+
(mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_DMABUF_OFFSET)) {
492+
if (have_dmabuf) {
493+
uct_rocm_base_dmabuf_export(base_addr, base_size, mem_type,
494+
&dmabuf_fd, &dmabuf_offset);
495+
}
496+
497+
if (mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_DMABUF_FD) {
498+
mem_attr_p->dmabuf_fd = dmabuf_fd;
499+
} else {
500+
ucs_close_fd(&dmabuf_fd);
501+
}
485502

486-
if (mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_DMABUF_OFFSET) {
487-
if (!is_exported) {
488-
uct_rocm_base_dmabuf_export(addr, length, mem_type, &dmabuf_fd,
489-
&dmabuf_offset);
503+
if (mem_attr_p->field_mask & UCT_MD_MEM_ATTR_V2_FIELD_DMABUF_OFFSET) {
504+
mem_attr_p->dmabuf_offset = dmabuf_offset +
505+
UCS_PTR_BYTE_DIFF(base_addr, addr);
490506
}
491-
mem_attr_p->dmabuf_offset = dmabuf_offset;
492507
}
493508

494509
if (mem_type == UCS_MEMORY_TYPE_ROCM) {

src/uct/rocm/base/rocm_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ ucs_status_t uct_rocm_base_detect_memory_type(uct_md_h md, const void *addr,
4141
size_t length,
4242
ucs_memory_type_t *mem_type_p);
4343
ucs_status_t uct_rocm_base_mem_query(uct_md_h md, const void *addr,
44-
const size_t length,
44+
size_t length, int have_dmabuf,
4545
uct_md_mem_attr_v2_t *mem_attr_p);
4646
ucs_status_t uct_rocm_base_get_link_type(hsa_amd_link_info_type_t *type);
4747
uct_rocm_amd_gpu_product_t uct_rocm_base_get_gpu_product(void);

src/uct/rocm/copy/rocm_copy_md.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static ucs_config_field_t uct_rocm_copy_md_config_table[] = {
3636
ucs_offsetof(uct_rocm_copy_md_config_t, rcache),
3737
UCS_CONFIG_TYPE_TABLE(ucs_config_rcache_table)},
3838

39-
{"DMABUF", "no",
39+
{"DMABUF", "try",
4040
"Enable using cross-device dmabuf file descriptor",
4141
ucs_offsetof(uct_rocm_copy_md_config_t, enable_dmabuf),
4242
UCS_CONFIG_TYPE_TERNARY},
@@ -282,6 +282,16 @@ static ucs_status_t uct_rocm_copy_mem_free(uct_md_h md, uct_mem_h memh)
282282
return UCS_OK;
283283
}
284284

285+
static ucs_status_t
286+
uct_rocm_copy_mem_query(uct_md_h uct_md, const void *addr, size_t length,
287+
uct_md_mem_attr_v2_t *mem_attr_p)
288+
{
289+
uct_rocm_copy_md_t *md = ucs_derived_of(uct_md, uct_rocm_copy_md_t);
290+
291+
return uct_rocm_base_mem_query(uct_md, addr, length, md->have_dmabuf,
292+
mem_attr_p);
293+
}
294+
285295
static uct_md_ops_t md_ops = {
286296
.close = uct_rocm_copy_md_close,
287297
.query = uct_rocm_copy_md_query,
@@ -290,7 +300,7 @@ static uct_md_ops_t md_ops = {
290300
.mem_advise = (uct_md_mem_advise_func_t)ucs_empty_function_return_unsupported,
291301
.mem_reg = uct_rocm_copy_mem_reg,
292302
.mem_dereg = uct_rocm_copy_mem_dereg,
293-
.mem_query = uct_rocm_base_mem_query,
303+
.mem_query = uct_rocm_copy_mem_query,
294304
.mkey_pack = uct_rocm_copy_mkey_pack,
295305
.mem_attach = (uct_md_mem_attach_func_t)ucs_empty_function_return_unsupported,
296306
.detect_memory_type = uct_rocm_base_detect_memory_type,
@@ -351,7 +361,7 @@ static uct_md_ops_t md_rcache_ops = {
351361
.mem_advise = (uct_md_mem_advise_func_t)ucs_empty_function_return_unsupported,
352362
.mem_reg = uct_rocm_copy_mem_rcache_reg,
353363
.mem_dereg = uct_rocm_copy_mem_rcache_dereg,
354-
.mem_query = uct_rocm_base_mem_query,
364+
.mem_query = uct_rocm_copy_mem_query,
355365
.mkey_pack = uct_rocm_copy_mkey_pack,
356366
.mem_attach = (uct_md_mem_attach_func_t)ucs_empty_function_return_unsupported,
357367
.detect_memory_type = uct_rocm_base_detect_memory_type,
@@ -428,7 +438,8 @@ uct_rocm_copy_md_open(uct_component_h component, const char *md_name,
428438
have_dmabuf = uct_rocm_base_is_dmabuf_supported();
429439
if ((md_config->enable_dmabuf == UCS_YES) && !have_dmabuf) {
430440
ucs_error("ROCm dmabuf support requested but not found");
431-
return UCS_ERR_UNSUPPORTED;
441+
status = UCS_ERR_UNSUPPORTED;
442+
goto err;
432443
}
433444

434445
if (md_config->enable_dmabuf != UCS_NO) {

test/gtest/uct/test_md.cc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,10 +542,16 @@ UCS_TEST_P(test_md, mem_type_detect_mds) {
542542
ASSERT_UCS_OK(status);
543543
EXPECT_EQ(alloc_mem_type, mem_attr.mem_type);
544544
if ((alloc_mem_type == UCS_MEMORY_TYPE_CUDA) ||
545+
(alloc_mem_type == UCS_MEMORY_TYPE_ROCM) ||
545546
(alloc_mem_type == UCS_MEMORY_TYPE_ZE_HOST) ||
546547
(alloc_mem_type == UCS_MEMORY_TYPE_ZE_DEVICE) ||
547548
(alloc_mem_type == UCS_MEMORY_TYPE_ZE_MANAGED)) {
548-
EXPECT_EQ(buffer_size, mem_attr.alloc_length);
549+
/* ROCm HSA may round sizeInBytes up to a page */
550+
if (alloc_mem_type == UCS_MEMORY_TYPE_ROCM) {
551+
EXPECT_GE(mem_attr.alloc_length, buffer_size);
552+
} else {
553+
EXPECT_EQ(buffer_size, mem_attr.alloc_length);
554+
}
549555
EXPECT_EQ(address, mem_attr.base_address);
550556
} else {
551557
EXPECT_EQ(slice_length, mem_attr.alloc_length);
@@ -1277,6 +1283,30 @@ UCS_TEST_P(test_md_dmabuf, mem_query_dmabuf)
12771283

12781284
UCT_MD_INSTANTIATE_TEST_CASE(test_md_dmabuf)
12791285

1286+
class test_rocm_copy : public test_md {
1287+
};
1288+
1289+
UCS_TEST_P(test_rocm_copy, dmabuf_disable, "ROCM_COPY_DMABUF=no")
1290+
{
1291+
EXPECT_EQ(0, md_attr().dmabuf_mem_types);
1292+
if (!(md_attr().access_mem_types & UCS_BIT(UCS_MEMORY_TYPE_ROCM)) ||
1293+
!mem_buffer::is_mem_type_supported(UCS_MEMORY_TYPE_ROCM)) {
1294+
UCS_TEST_SKIP_R("ROCm memory is not supported");
1295+
}
1296+
1297+
mem_buffer mem_buf(ucs_get_page_size(), UCS_MEMORY_TYPE_ROCM);
1298+
uct_md_mem_attr_t mem_attr = {};
1299+
1300+
mem_attr.field_mask = UCT_MD_MEM_ATTR_FIELD_DMABUF_FD |
1301+
UCT_MD_MEM_ATTR_FIELD_DMABUF_OFFSET;
1302+
ASSERT_UCS_OK(uct_md_mem_query(md(), mem_buf.ptr(), mem_buf.size(),
1303+
&mem_attr));
1304+
EXPECT_EQ(UCT_DMABUF_FD_INVALID, mem_attr.dmabuf_fd);
1305+
EXPECT_EQ(0ul, mem_attr.dmabuf_offset);
1306+
}
1307+
1308+
_UCT_MD_INSTANTIATE_TEST_CASE(test_rocm_copy, rocm_cpy)
1309+
12801310
class test_cuda : public test_md
12811311
{
12821312
};

0 commit comments

Comments
 (0)