Skip to content

Commit 0365062

Browse files
committed
UCP/RNDV: Use four read paths on ConnectX-9 XDR
1 parent d0e1f7a commit 0365062

10 files changed

Lines changed: 274 additions & 30 deletions

File tree

docs/source/faq.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,10 @@ and NUMA locality.
256256

257257
#### Is it possible to use more than 2 rails?
258258

259-
Yes, by setting `UCX_MAX_RNDV_RAILS=<num-rails>`. Currently up to 4 are supported.
259+
Yes, by setting `UCX_MAX_RNDV_RAILS=<num-rails>`. Up to 4 are supported. With
260+
the default `auto` setting, certain transports (for example ConnectX-9 XDR for
261+
RDMA read) may automatically use additional paths on a single device beyond the
262+
two-device baseline.
260263

261264
#### Is it possible that each process would just use the closest device?
262265

src/ucp/core/ucp_context.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <ucs/type/init_once.h>
3030
#include <ucs/vfs/base/vfs_cb.h>
3131
#include <ucs/vfs/base/vfs_obj.h>
32+
#include <limits.h>
3233
#include <string.h>
3334
#include <dlfcn.h>
3435

@@ -227,11 +228,15 @@ static ucs_config_field_t ucp_context_config_table[] = {
227228
ucs_offsetof(ucp_context_config_t, max_eager_lanes), UCS_CONFIG_TYPE_UINT},
228229

229230
{"MAX_RNDV_LANES", NULL,"",
230-
ucs_offsetof(ucp_context_config_t, max_rndv_lanes), UCS_CONFIG_TYPE_UINT},
231+
ucs_offsetof(ucp_context_config_t, max_rndv_lanes_config),
232+
UCS_CONFIG_TYPE_ULUNITS},
231233

232-
{"MAX_RNDV_RAILS", "2",
233-
"Maximal number of devices on which a rendezvous operation may be executed in parallel",
234-
ucs_offsetof(ucp_context_config_t, max_rndv_lanes), UCS_CONFIG_TYPE_UINT},
234+
{"MAX_RNDV_RAILS", "auto",
235+
"Maximal number of devices on which a rendezvous operation may be executed\n"
236+
"in parallel. With 'auto', the default is two devices, while a transport\n"
237+
"may expose additional paths needed by a single device.",
238+
ucs_offsetof(ucp_context_config_t, max_rndv_lanes_config),
239+
UCS_CONFIG_TYPE_ULUNITS},
235240

236241
{"MAX_RMA_LANES", NULL, "",
237242
ucs_offsetof(ucp_context_config_t, max_rma_lanes), UCS_CONFIG_TYPE_UINT},
@@ -2367,6 +2372,23 @@ static double ucp_context_get_protov1_memcpy_bw()
23672372
UCP_CPU_EST_BCOPY_BW_DEFAULT_PROTOV1;
23682373
}
23692374

2375+
static ucs_status_t
2376+
ucp_context_resolve_rndv_config(ucp_context_config_t *config)
2377+
{
2378+
if (config->max_rndv_lanes_config == UCS_ULUNITS_AUTO) {
2379+
config->max_rndv_lanes = UCP_MAX_RNDV_LANES_DEFAULT;
2380+
} else if ((config->max_rndv_lanes_config == UCS_ULUNITS_INF) ||
2381+
(config->max_rndv_lanes_config > UINT_MAX)) {
2382+
ucs_error("maximum number of rendezvous lanes must not exceed %u",
2383+
UINT_MAX);
2384+
return UCS_ERR_INVALID_PARAM;
2385+
} else {
2386+
config->max_rndv_lanes = config->max_rndv_lanes_config;
2387+
}
2388+
2389+
return UCS_OK;
2390+
}
2391+
23702392
static int
23712393
ucp_dynamic_tl_switch_config_valid(const ucp_context_config_t *config)
23722394
{
@@ -2404,6 +2426,11 @@ static ucs_status_t ucp_fill_config(ucp_context_h context,
24042426
goto err;
24052427
}
24062428

2429+
status = ucp_context_resolve_rndv_config(&context->config.ext);
2430+
if (status != UCS_OK) {
2431+
goto err_free_config_ext;
2432+
}
2433+
24072434
if (context->config.ext.estimated_num_eps != UCS_ULUNITS_AUTO) {
24082435
/* num_eps was set via the env variable. Override current value */
24092436
context->config.est_num_eps = context->config.ext.estimated_num_eps;

src/ucp/core/ucp_context.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ typedef enum {
6060
} ucp_reg_devices_mode_t;
6161

6262

63+
#define UCP_MAX_RNDV_LANES_DEFAULT 2
64+
65+
6366
static UCS_F_ALWAYS_INLINE ucp_reg_devices_mode_t
6467
ucp_reg_devices_mode(unsigned long max_hca_per_gpu)
6568
{
@@ -150,6 +153,8 @@ typedef struct ucp_context_config {
150153
int adaptive_progress;
151154
/** Eager-am multi-lane support */
152155
unsigned max_eager_lanes;
156+
/** Raw rendezvous lane limit before resolving the auto value */
157+
unsigned long max_rndv_lanes_config;
153158
/** Rendezvous-get multi-lane support */
154159
unsigned max_rndv_lanes;
155160
/** RMA multi-lane support */

src/ucp/rndv/rndv_get.c

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,57 @@
1717

1818
#define UCP_PROTO_RNDV_GET_DESC "read from remote"
1919

20+
static ucp_lane_index_t
21+
ucp_proto_rndv_get_max_lanes(const ucp_proto_init_params_t *init_params)
22+
{
23+
ucp_context_t *context = init_params->worker->context;
24+
const ucp_ep_config_key_t *ep_key = init_params->ep_config_key;
25+
ucp_lane_index_t max_lanes = context->config.ext.max_rndv_lanes;
26+
const uct_iface_attr_t *iface_attr;
27+
ucp_lane_index_t lane;
28+
29+
if (context->config.ext.max_rndv_lanes_config != UCS_ULUNITS_AUTO) {
30+
return max_lanes;
31+
}
32+
33+
for (lane = 0; lane < ep_key->num_lanes; ++lane) {
34+
if (!(ep_key->lanes[lane].lane_types &
35+
UCS_BIT(UCP_LANE_TYPE_RMA_BW))) {
36+
continue;
37+
}
38+
39+
iface_attr = ucp_proto_common_get_iface_attr(init_params, lane);
40+
if (!(iface_attr->cap.flags & UCT_IFACE_FLAG_GET_ZCOPY)) {
41+
continue;
42+
}
43+
44+
max_lanes = ucs_max(max_lanes,
45+
ucs_min(iface_attr->dev_num_paths,
46+
UCP_PROTO_MAX_LANES));
47+
}
48+
49+
return max_lanes;
50+
}
51+
52+
static void
53+
ucp_proto_rndv_get_add_proto(ucp_proto_multi_init_params_t *params)
54+
{
55+
ucp_proto_rndv_bulk_priv_t rpriv;
56+
ucp_proto_perf_t *perf;
57+
ucs_status_t status;
58+
59+
status = ucp_proto_rndv_bulk_init(params, UCP_PROTO_RNDV_GET_DESC,
60+
UCP_PROTO_RNDV_ATS_NAME, &perf, &rpriv);
61+
if (status != UCS_OK) {
62+
return;
63+
}
64+
65+
ucp_proto_select_add_proto(&params->super.super, params->super.cfg_thresh,
66+
params->super.cfg_priority, perf, &rpriv,
67+
UCP_PROTO_MULTI_EXTENDED_PRIV_SIZE(&rpriv,
68+
mpriv));
69+
}
70+
2071
static void
2172
ucp_proto_rndv_get_common_probe(const ucp_proto_init_params_t *init_params,
2273
uint64_t rndv_modes, size_t max_length,
@@ -26,6 +77,8 @@ ucp_proto_rndv_get_common_probe(const ucp_proto_init_params_t *init_params,
2677
const ucp_memory_info_t *reg_mem_info)
2778
{
2879
ucp_context_t *context = init_params->worker->context;
80+
ucp_lane_index_t max_lanes =
81+
ucp_proto_rndv_get_max_lanes(init_params);
2982
ucp_proto_multi_init_params_t params = {
3083
.super.super = *init_params,
3184
.super.cfg_thresh = ucp_proto_rndv_cfg_thresh(context, rndv_modes),
@@ -58,25 +111,18 @@ ucp_proto_rndv_get_common_probe(const ucp_proto_init_params_t *init_params,
58111
.opt_align_offs = ucs_offsetof(uct_iface_attr_t,
59112
cap.get.opt_zcopy_align),
60113
};
61-
ucp_proto_rndv_bulk_priv_t rpriv;
62-
ucp_proto_perf_t *perf;
63-
ucs_status_t status;
64114

65115
if (!ucp_proto_rndv_op_check(init_params, UCP_OP_ID_RNDV_RECV,
66116
support_ppln)) {
67117
return;
68118
}
69119

70-
status = ucp_proto_rndv_bulk_init(&params, UCP_PROTO_RNDV_GET_DESC,
71-
UCP_PROTO_RNDV_ATS_NAME, &perf, &rpriv);
72-
if (status != UCS_OK) {
73-
return;
74-
}
120+
ucp_proto_rndv_get_add_proto(&params);
75121

76-
ucp_proto_select_add_proto(&params.super.super, params.super.cfg_thresh,
77-
params.super.cfg_priority, perf, &rpriv,
78-
UCP_PROTO_MULTI_EXTENDED_PRIV_SIZE(&rpriv,
79-
mpriv));
122+
if (max_lanes > params.max_lanes) {
123+
params.max_lanes = max_lanes;
124+
ucp_proto_rndv_get_add_proto(&params);
125+
}
80126
}
81127

82128
static UCS_F_ALWAYS_INLINE ucs_status_t

src/uct/ib/base/ib_device.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ static uct_ib_device_spec_t uct_ib_builtin_device_specs[] = {
160160
UCT_IB_DEVICE_FLAG_DC_V2, 80},
161161
{"ConnectX-9", {0x15b3, 4133},
162162
UCT_IB_DEVICE_FLAG_MELLANOX | UCT_IB_DEVICE_FLAG_MLX5_PRM |
163-
UCT_IB_DEVICE_FLAG_DC_V2, 90},
163+
UCT_IB_DEVICE_FLAG_DC_V2 | UCT_IB_DEVICE_FLAG_XDR_READ_4_PATHS, 90},
164164
{"ConnectX-10", {0x15b3, 4135},
165165
UCT_IB_DEVICE_FLAG_MELLANOX | UCT_IB_DEVICE_FLAG_MLX5_PRM |
166166
UCT_IB_DEVICE_FLAG_DC_V2, 100},

src/uct/ib/base/ib_device.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,18 @@ typedef enum uct_ib_roce_version {
9090

9191

9292
enum {
93-
UCT_IB_DEVICE_FLAG_MLX4_PRM = UCS_BIT(1), /* Device supports mlx4 PRM */
94-
UCT_IB_DEVICE_FLAG_MLX5_PRM = UCS_BIT(2), /* Device supports mlx5 PRM */
95-
UCT_IB_DEVICE_FLAG_MELLANOX = UCS_BIT(3), /* Mellanox device */
96-
UCT_IB_DEVICE_FLAG_SRQ = UCS_BIT(4), /* Supports SRQ */
97-
UCT_IB_DEVICE_FLAG_LINK_IB = UCS_BIT(5), /* Require only IB */
98-
UCT_IB_DEVICE_FLAG_DC_V1 = UCS_BIT(6), /* Device supports DC ver 1 */
99-
UCT_IB_DEVICE_FLAG_DC_V2 = UCS_BIT(7), /* Device supports DC ver 2 */
100-
UCT_IB_DEVICE_FLAG_AV = UCS_BIT(8), /* Device supports compact AV */
101-
UCT_IB_DEVICE_FLAG_DC = UCT_IB_DEVICE_FLAG_DC_V1 |
102-
UCT_IB_DEVICE_FLAG_DC_V2, /* Device supports DC */
103-
UCT_IB_DEVICE_FAILED = UCS_BIT(9) /* Got fatal error */
93+
UCT_IB_DEVICE_FLAG_MLX4_PRM = UCS_BIT(1), /* Device supports mlx4 PRM */
94+
UCT_IB_DEVICE_FLAG_MLX5_PRM = UCS_BIT(2), /* Device supports mlx5 PRM */
95+
UCT_IB_DEVICE_FLAG_MELLANOX = UCS_BIT(3), /* Mellanox device */
96+
UCT_IB_DEVICE_FLAG_SRQ = UCS_BIT(4), /* Supports SRQ */
97+
UCT_IB_DEVICE_FLAG_LINK_IB = UCS_BIT(5), /* Require only IB */
98+
UCT_IB_DEVICE_FLAG_DC_V1 = UCS_BIT(6), /* Device supports DC ver 1 */
99+
UCT_IB_DEVICE_FLAG_DC_V2 = UCS_BIT(7), /* Device supports DC ver 2 */
100+
UCT_IB_DEVICE_FLAG_AV = UCS_BIT(8), /* Device supports compact AV */
101+
UCT_IB_DEVICE_FLAG_DC = UCT_IB_DEVICE_FLAG_DC_V1 |
102+
UCT_IB_DEVICE_FLAG_DC_V2, /* Device supports DC */
103+
UCT_IB_DEVICE_FAILED = UCS_BIT(9), /* Got fatal error */
104+
UCT_IB_DEVICE_FLAG_XDR_READ_4_PATHS = UCS_BIT(10) /* XDR: 4 read paths */
104105
};
105106

106107

src/uct/ib/base/ib_iface.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
*/
3939
#define UCT_IB_NDR_READ_PATH_BANDWIDTH 38e9
4040
#define UCT_IB_XDR_READ_PATH_BANDWIDTH 35e9
41+
#define UCT_IB_XDR_READ_NUM_PATHS 4
4142

4243
/**
4344
* Minimal NDR single path ratio.
@@ -191,7 +192,8 @@ ucs_config_field_t uct_ib_iface_config_table[] = {
191192
"to the port link layer:\n"
192193
" RoCE - "UCS_PP_MAKE_STRING(UCT_IB_DEV_MAX_PORTS) " for LAG port, otherwise - 1.\n"
193194
" InfiniBand - As the number of path bits enabled by fabric's LMC value and selected\n"
194-
" by "UCS_DEFAULT_ENV_PREFIX UCT_IB_CONFIG_PREFIX"LID_PATH_BITS configuration.",
195+
" by "UCS_DEFAULT_ENV_PREFIX UCT_IB_CONFIG_PREFIX"LID_PATH_BITS configuration.\n"
196+
" ConnectX-9 XDR ports expose four paths for RDMA read bandwidth.",
195197
ucs_offsetof(uct_ib_iface_config_t, num_paths), UCS_CONFIG_TYPE_ULUNITS},
196198

197199
{"ROCE_LOCAL_SUBNET", "n",
@@ -1400,6 +1402,8 @@ static unsigned uct_ib_iface_roce_lag_level(uct_ib_iface_t *iface)
14001402
static void uct_ib_iface_set_num_paths(uct_ib_iface_t *iface,
14011403
const uct_ib_iface_config_t *config)
14021404
{
1405+
const uct_ib_device_spec_t *dev_spec;
1406+
14031407
if (config->num_paths == UCS_ULUNITS_AUTO) {
14041408
if (uct_ib_iface_is_roce(iface)) {
14051409
/* RoCE - number of paths is RoCE LAG level */
@@ -1410,6 +1414,13 @@ static void uct_ib_iface_set_num_paths(uct_ib_iface_t *iface,
14101414
iface->num_paths = iface->path_bits_count;
14111415
}
14121416

1417+
dev_spec = uct_ib_device_spec(uct_ib_iface_device(iface));
1418+
if (uct_ib_iface_port_is_xdr(iface) &&
1419+
(dev_spec->flags & UCT_IB_DEVICE_FLAG_XDR_READ_4_PATHS)) {
1420+
iface->num_paths = ucs_max(iface->num_paths,
1421+
UCT_IB_XDR_READ_NUM_PATHS);
1422+
}
1423+
14131424
if ((iface->num_paths == 1) &&
14141425
(uct_ib_iface_port_active_speed(iface) >= UCT_IB_SPEED_NDR)) {
14151426
iface->num_paths = 2;

test/gtest/ucp/test_ucp_context.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,54 @@ UCS_TEST_P(test_ucp_context, max_hca_per_gpu_config)
7272
EXPECT_EQ(2u, ucp_reg_devices_count(e->ucph()->config.ext.max_hca_per_gpu));
7373
}
7474

75+
UCS_TEST_P(test_ucp_context, rndv_lane_default)
76+
{
77+
entity *e = create_entity();
78+
79+
EXPECT_EQ(UCS_ULUNITS_AUTO,
80+
e->ucph()->config.ext.max_rndv_lanes_config);
81+
EXPECT_EQ(UCP_MAX_RNDV_LANES_DEFAULT,
82+
e->ucph()->config.ext.max_rndv_lanes);
83+
}
84+
85+
UCS_TEST_P(test_ucp_context, rndv_lane_config_override)
86+
{
87+
modify_config("MAX_RNDV_RAILS", "3");
88+
89+
entity *e = create_entity();
90+
EXPECT_EQ(3ul, e->ucph()->config.ext.max_rndv_lanes_config);
91+
EXPECT_EQ(3u, e->ucph()->config.ext.max_rndv_lanes);
92+
}
93+
94+
UCS_TEST_P(test_ucp_context, rndv_lane_alias_override)
95+
{
96+
modify_config("MAX_RNDV_LANES", "3");
97+
98+
entity *e = create_entity();
99+
EXPECT_EQ(3ul, e->ucph()->config.ext.max_rndv_lanes_config);
100+
EXPECT_EQ(3u, e->ucph()->config.ext.max_rndv_lanes);
101+
}
102+
103+
UCS_TEST_P(test_ucp_context, rndv_lane_config_invalid_inf)
104+
{
105+
ucs::handle<ucp_config_t*> config;
106+
UCS_TEST_CREATE_HANDLE(ucp_config_t*, config, ucp_config_release,
107+
ucp_config_read, NULL, NULL);
108+
109+
ASSERT_UCS_OK(ucp_config_modify(config.get(), "MAX_RNDV_RAILS", "inf"));
110+
111+
ucp_context_h ucph;
112+
ucs_status_t status;
113+
{
114+
scoped_log_handler slh(hide_errors_logger);
115+
status = ucp_init(&get_variant_ctx_params(), config.get(), &ucph);
116+
}
117+
EXPECT_EQ(UCS_ERR_INVALID_PARAM, status);
118+
if (status == UCS_OK) {
119+
ucp_cleanup(ucph);
120+
}
121+
}
122+
75123
UCP_INSTANTIATE_TEST_CASE_TLS(test_ucp_context, all, "all")
76124

77125
class test_ucp_aliases : public test_ucp_context {

0 commit comments

Comments
 (0)