Skip to content

Commit 9ec5218

Browse files
authored
Merge pull request #8840 from Akshay-Venkatesh/topic/revert-cuda-copy-notification-v.14.x
UCT/CUDA_COPY: use EVENT_FD instead of EVENT_ASYNC_CB - v1.14.x
2 parents d83ef40 + 348c9dc commit 9ec5218

File tree

11 files changed

+264
-128
lines changed

11 files changed

+264
-128
lines changed

src/ucs/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ noinst_HEADERS = \
127127
type/float8.h \
128128
async/async.h \
129129
async/pipe.h \
130+
async/eventfd.h \
130131
async/signal.h \
131132
async/thread.h \
132133
async/async_int.h
@@ -145,6 +146,7 @@ libucs_la_SOURCES = \
145146
async/async.c \
146147
async/signal.c \
147148
async/pipe.c \
149+
async/eventfd.c \
148150
async/thread.c \
149151
config/global_opts.c \
150152
config/ucm_opts.c \

src/ucs/async/eventfd.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2023. ALL RIGHTS RESERVED.
3+
*
4+
* See file LICENSE for terms.
5+
*/
6+
7+
#ifdef HAVE_CONFIG_H
8+
# include "config.h"
9+
#endif
10+
11+
#include "eventfd.h"
12+
13+
#include <ucs/debug/log.h>
14+
#include <ucs/sys/sys.h>
15+
16+
17+
typedef ssize_t (*ucs_async_eventfd_cb_t)(int fd, void *buf, size_t count);
18+
19+
20+
static inline ucs_status_t
21+
ucs_async_eventfd_common_io(int fd, int blocking, ucs_async_eventfd_cb_t cb)
22+
{
23+
uint64_t dummy = 1;
24+
int ret;
25+
26+
do {
27+
ret = cb(fd, &dummy, sizeof(dummy));
28+
if (ret > 0) {
29+
return UCS_OK;
30+
}
31+
32+
if ((ret < 0) && (errno != EAGAIN) && (errno != EINTR)) {
33+
ucs_error("eventfd error (fd %d blocking %d): %m", fd, blocking);
34+
return UCS_ERR_IO_ERROR;
35+
}
36+
} while (blocking);
37+
38+
return UCS_ERR_NO_PROGRESS;
39+
}
40+
41+
ucs_status_t ucs_async_eventfd_create(int *fd_p)
42+
{
43+
int local_fd;
44+
45+
local_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
46+
if (local_fd == -1) {
47+
ucs_error("failed to create event fd: %m");
48+
return UCS_ERR_IO_ERROR;
49+
}
50+
51+
*fd_p = local_fd;
52+
return UCS_OK;
53+
}
54+
55+
void ucs_async_eventfd_destroy(int fd)
56+
{
57+
if (fd != UCS_ASYNC_EVENTFD_INVALID_FD) {
58+
close(fd);
59+
}
60+
}
61+
62+
ucs_status_t ucs_async_eventfd_poll(int fd)
63+
{
64+
return ucs_async_eventfd_common_io(fd, 0, (ucs_async_eventfd_cb_t)read);
65+
}
66+
67+
ucs_status_t ucs_async_eventfd_signal(int fd)
68+
{
69+
return ucs_async_eventfd_common_io(fd, 1, (ucs_async_eventfd_cb_t)write);
70+
}

src/ucs/async/eventfd.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2023. ALL RIGHTS RESERVED.
3+
*
4+
* See file LICENSE for terms.
5+
*/
6+
7+
#ifndef UCS_ASYNC_EVENTFD_H
8+
#define UCS_ASYNC_EVENTFD_H
9+
10+
#include <ucs/type/status.h>
11+
#include <sys/eventfd.h>
12+
13+
BEGIN_C_DECLS
14+
15+
16+
/**
17+
* Represent either an unitialized or a closed event file descriptor.
18+
*/
19+
#define UCS_ASYNC_EVENTFD_INVALID_FD (-1)
20+
21+
22+
/**
23+
* @ingroup UCS_RESOURCE
24+
*
25+
* Create an event file descriptor. This file descriptor can later be passed as
26+
* arguments to poll/signal functions to wait for notifications or to notify
27+
* pollers.
28+
*
29+
* @param fd Pointer to integer which is populated with a file descriptor.
30+
*/
31+
ucs_status_t ucs_async_eventfd_create(int *fd);
32+
33+
34+
/**
35+
* @ingroup UCS_RESOURCE
36+
*
37+
* Destroy an event file descriptor.
38+
*
39+
* @param fd File descriptor to be closed.
40+
*/
41+
void ucs_async_eventfd_destroy(int fd);
42+
43+
44+
/**
45+
* @ingroup UCS_RESOURCE
46+
*
47+
* Notify a file descriptor when it is polled. An appropriate error is returned
48+
* upon failure.
49+
*
50+
* @param fd File descriptor which will be notified.
51+
*/
52+
ucs_status_t ucs_async_eventfd_signal(int fd);
53+
54+
55+
/**
56+
* @ingroup UCS_RESOURCE
57+
*
58+
* Poll on a file descriptor for incoming notifications. If no notifications are
59+
* observed then UCS_ERR_NO_PROGRESS is returned. An appropriate error is
60+
* returned upon failure.
61+
*
62+
* @param fd File descriptor to be polled on.
63+
*/
64+
ucs_status_t ucs_async_eventfd_poll(int fd);
65+
66+
END_C_DECLS
67+
68+
#endif

src/uct/cuda/base/cuda_iface.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,53 @@ uct_cuda_base_query_devices(
3636
return uct_cuda_base_query_devices_common(md, UCT_DEVICE_TYPE_ACC,
3737
tl_devices_p, num_tl_devices_p);
3838
}
39+
40+
#if (__CUDACC_VER_MAJOR__ >= 100000)
41+
void CUDA_CB uct_cuda_base_iface_stream_cb_fxn(void *arg)
42+
#else
43+
void CUDA_CB uct_cuda_base_iface_stream_cb_fxn(CUstream hStream, CUresult status,
44+
void *arg)
45+
#endif
46+
{
47+
uct_cuda_iface_t *cuda_iface = arg;
48+
49+
ucs_async_eventfd_signal(cuda_iface->eventfd);
50+
}
51+
52+
ucs_status_t uct_cuda_base_iface_event_fd_get(uct_iface_h tl_iface, int *fd_p)
53+
{
54+
uct_cuda_iface_t *iface = ucs_derived_of(tl_iface, uct_cuda_iface_t);
55+
ucs_status_t status;
56+
57+
if (iface->eventfd == UCS_ASYNC_EVENTFD_INVALID_FD) {
58+
status = ucs_async_eventfd_create(&iface->eventfd);
59+
if (status != UCS_OK) {
60+
return status;
61+
}
62+
}
63+
64+
*fd_p = iface->eventfd;
65+
return UCS_OK;
66+
}
67+
68+
UCS_CLASS_INIT_FUNC(uct_cuda_iface_t, uct_iface_ops_t *tl_ops,
69+
uct_iface_internal_ops_t *ops, uct_md_h md,
70+
uct_worker_h worker, const uct_iface_params_t *params,
71+
const uct_iface_config_t *tl_config,
72+
const char *dev_name)
73+
{
74+
UCS_CLASS_CALL_SUPER_INIT(uct_base_iface_t, tl_ops, ops, md, worker, params,
75+
tl_config UCS_STATS_ARG(params->stats_root)
76+
UCS_STATS_ARG(dev_name));
77+
78+
self->eventfd = UCS_ASYNC_EVENTFD_INVALID_FD;
79+
80+
return UCS_OK;
81+
}
82+
83+
static UCS_CLASS_CLEANUP_FUNC(uct_cuda_iface_t)
84+
{
85+
ucs_async_eventfd_destroy(self->eventfd);
86+
}
87+
88+
UCS_CLASS_DEFINE(uct_cuda_iface_t, uct_base_iface_t);

src/uct/cuda/base/cuda_iface.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <uct/base/uct_iface.h>
1010
#include <ucs/sys/preprocessor.h>
1111
#include <ucs/profile/profile.h>
12+
#include <ucs/async/eventfd.h>
1213
#include <cuda_runtime.h>
1314
#include <cuda.h>
1415
#include <nvml.h>
@@ -141,6 +142,11 @@ typedef enum uct_cuda_base_gen {
141142
} uct_cuda_base_gen_t;
142143

143144

145+
typedef struct uct_cuda_iface {
146+
uct_base_iface_t super;
147+
int eventfd;
148+
} uct_cuda_iface_t;
149+
144150
ucs_status_t
145151
uct_cuda_base_query_devices_common(
146152
uct_md_h md, uct_device_type_t dev_type,
@@ -155,4 +161,18 @@ ucs_status_t
155161
uct_cuda_base_get_sys_dev(CUdevice cuda_device,
156162
ucs_sys_device_t *sys_dev_p);
157163

164+
ucs_status_t uct_cuda_base_iface_event_fd_get(uct_iface_h tl_iface, int *fd_p);
165+
166+
#if (__CUDACC_VER_MAJOR__ >= 100000)
167+
void CUDA_CB uct_cuda_base_iface_stream_cb_fxn(void *arg);
168+
#else
169+
void CUDA_CB uct_cuda_base_iface_stream_cb_fxn(CUstream hStream, CUresult status,
170+
void *arg);
171+
#endif
172+
173+
UCS_CLASS_INIT_FUNC(uct_cuda_iface_t, uct_iface_ops_t *tl_ops,
174+
uct_iface_internal_ops_t *ops, uct_md_h md,
175+
uct_worker_h worker, const uct_iface_params_t *params,
176+
const uct_iface_config_t *tl_config, const char *dev_name);
177+
158178
#endif

src/uct/cuda/cuda_copy/cuda_copy_ep.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ static UCS_CLASS_INIT_FUNC(uct_cuda_copy_ep_t, const uct_ep_params_t *params)
2626
uct_cuda_copy_iface_t);
2727

2828
UCT_EP_PARAMS_CHECK_DEV_IFACE_ADDRS(params);
29-
UCS_CLASS_CALL_SUPER_INIT(uct_base_ep_t, &iface->super);
29+
UCS_CLASS_CALL_SUPER_INIT(uct_base_ep_t, &iface->super.super);
3030

3131
return UCS_OK;
3232
}

src/uct/cuda/cuda_copy/cuda_copy_iface.c

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <uct/cuda/base/cuda_md.h>
1616
#include <ucs/type/class.h>
1717
#include <ucs/sys/string.h>
18-
#include <ucs/async/async.h>
18+
#include <ucs/async/eventfd.h>
1919
#include <ucs/arch/cpu.h>
2020

2121

@@ -73,7 +73,7 @@ static ucs_status_t uct_cuda_copy_iface_query(uct_iface_h tl_iface,
7373
{
7474
uct_cuda_copy_iface_t *iface = ucs_derived_of(tl_iface, uct_cuda_copy_iface_t);
7575

76-
uct_base_iface_query(&iface->super, iface_attr);
76+
uct_base_iface_query(&iface->super.super, iface_attr);
7777

7878
iface_attr->iface_addr_len = sizeof(uct_cuda_copy_iface_addr_t);
7979
iface_attr->device_addr_len = 0;
@@ -87,7 +87,7 @@ static ucs_status_t uct_cuda_copy_iface_query(uct_iface_h tl_iface,
8787

8888
iface_attr->cap.event_flags = UCT_IFACE_FLAG_EVENT_SEND_COMP |
8989
UCT_IFACE_FLAG_EVENT_RECV |
90-
UCT_IFACE_FLAG_EVENT_ASYNC_CB;
90+
UCT_IFACE_FLAG_EVENT_FD;
9191

9292
iface_attr->cap.put.max_short = UINT_MAX;
9393
iface_attr->cap.put.max_bcopy = 0;
@@ -209,22 +209,6 @@ static unsigned uct_cuda_copy_iface_progress(uct_iface_h tl_iface)
209209
return count;
210210
}
211211

212-
#if (__CUDACC_VER_MAJOR__ >= 100000)
213-
static void CUDA_CB myHostFn(void *cuda_copy_iface)
214-
#else
215-
static void CUDA_CB myHostCallback(CUstream hStream, CUresult status,
216-
void *cuda_copy_iface)
217-
#endif
218-
{
219-
uct_cuda_copy_iface_t *iface = cuda_copy_iface;
220-
221-
ucs_assert(iface->async.event_cb != NULL);
222-
/* notify user */
223-
UCS_ASYNC_BLOCK(iface->super.worker->async);
224-
iface->async.event_cb(iface->async.event_arg, 0);
225-
UCS_ASYNC_UNBLOCK(iface->super.worker->async);
226-
}
227-
228212
static ucs_status_t uct_cuda_copy_iface_event_fd_arm(uct_iface_h tl_iface,
229213
unsigned events)
230214
{
@@ -242,18 +226,30 @@ static ucs_status_t uct_cuda_copy_iface_event_fd_arm(uct_iface_h tl_iface,
242226
}
243227
}
244228

229+
status = ucs_async_eventfd_poll(iface->super.eventfd);
230+
if (status == UCS_OK) {
231+
return UCS_ERR_BUSY;
232+
} else if (status == UCS_ERR_IO_ERROR) {
233+
return status;
234+
}
235+
236+
ucs_assertv(status == UCS_ERR_NO_PROGRESS, "%s", ucs_status_string(status));
237+
245238
ucs_queue_for_each_safe(q_desc, iter, &iface->active_queue, queue) {
246239
event_q = &q_desc->event_queue;
247240
stream = &q_desc->stream;
248241
if (!ucs_queue_is_empty(event_q)) {
249242
status =
250243
#if (__CUDACC_VER_MAJOR__ >= 100000)
251-
UCT_CUDADRV_FUNC_LOG_ERR(cuLaunchHostFunc(*stream,
252-
myHostFn, iface));
244+
UCT_CUDADRV_FUNC_LOG_ERR(
245+
cuLaunchHostFunc(*stream,
246+
uct_cuda_base_iface_stream_cb_fxn,
247+
&iface->super));
253248
#else
254-
UCT_CUDADRV_FUNC_LOG_ERR(cuStreamAddCallback(*stream,
255-
myHostCallback,
256-
iface, 0));
249+
UCT_CUDADRV_FUNC_LOG_ERR(
250+
cuStreamAddCallback(*stream,
251+
uct_cuda_base_iface_stream_cb_fxn,
252+
&iface->super, 0));
257253
#endif
258254
if (UCS_OK != status) {
259255
return status;
@@ -280,7 +276,7 @@ static uct_iface_ops_t uct_cuda_copy_iface_ops = {
280276
.iface_progress_enable = uct_base_iface_progress_enable,
281277
.iface_progress_disable = uct_base_iface_progress_disable,
282278
.iface_progress = uct_cuda_copy_iface_progress,
283-
.iface_event_fd_get = (uct_iface_event_fd_get_func_t)ucs_empty_function_return_success,
279+
.iface_event_fd_get = uct_cuda_base_iface_event_fd_get,
284280
.iface_event_arm = uct_cuda_copy_iface_event_fd_arm,
285281
.iface_close = UCS_CLASS_DELETE_FUNC_NAME(uct_cuda_copy_iface_t),
286282
.iface_query = uct_cuda_copy_iface_query,
@@ -409,11 +405,9 @@ static UCS_CLASS_INIT_FUNC(uct_cuda_copy_iface_t, uct_md_h md, uct_worker_h work
409405
ucs_memory_type_t src, dst;
410406
ucs_mpool_params_t mp_params;
411407

412-
UCS_CLASS_CALL_SUPER_INIT(uct_base_iface_t, &uct_cuda_copy_iface_ops,
408+
UCS_CLASS_CALL_SUPER_INIT(uct_cuda_iface_t, &uct_cuda_copy_iface_ops,
413409
&uct_cuda_copy_iface_internal_ops, md, worker,
414-
params,
415-
tl_config UCS_STATS_ARG(params->stats_root)
416-
UCS_STATS_ARG("cuda_copy"));
410+
params, tl_config, "cuda_copy");
417411

418412
if (strncmp(params->mode.device.dev_name,
419413
UCT_CUDA_DEV_NAME, strlen(UCT_CUDA_DEV_NAME)) != 0) {
@@ -438,9 +432,6 @@ static UCS_CLASS_INIT_FUNC(uct_cuda_copy_iface_t, uct_md_h md, uct_worker_h work
438432
return UCS_ERR_IO_ERROR;
439433
}
440434

441-
uct_iface_set_async_event_params(params, &self->async.event_cb,
442-
&self->async.event_arg);
443-
444435
ucs_queue_head_init(&self->active_queue);
445436

446437
for (src = 0; src < UCS_MEMORY_TYPE_LAST; ++src) {
@@ -463,7 +454,7 @@ static UCS_CLASS_CLEANUP_FUNC(uct_cuda_copy_iface_t)
463454
ucs_queue_head_t *event_q;
464455
ucs_memory_type_t src, dst;
465456

466-
uct_base_iface_progress_disable(&self->super.super,
457+
uct_base_iface_progress_disable(&self->super.super.super,
467458
UCT_PROGRESS_SEND | UCT_PROGRESS_RECV);
468459

469460
UCT_CUDADRV_FUNC_LOG_ERR(cuCtxGetCurrent(&cuda_context));
@@ -494,7 +485,7 @@ static UCS_CLASS_CLEANUP_FUNC(uct_cuda_copy_iface_t)
494485
ucs_mpool_cleanup(&self->cuda_event_desc, 1);
495486
}
496487

497-
UCS_CLASS_DEFINE(uct_cuda_copy_iface_t, uct_base_iface_t);
488+
UCS_CLASS_DEFINE(uct_cuda_copy_iface_t, uct_cuda_iface_t);
498489
UCS_CLASS_DEFINE_NEW_FUNC(uct_cuda_copy_iface_t, uct_iface_t, uct_md_h, uct_worker_h,
499490
const uct_iface_params_t*, const uct_iface_config_t*);
500491
static UCS_CLASS_DEFINE_DELETE_FUNC(uct_cuda_copy_iface_t, uct_iface_t);

0 commit comments

Comments
 (0)