Skip to content

Commit 9afe409

Browse files
committed
Preserve the original handle ptr
Signed-off-by: Larsen, Steffen <[email protected]>
1 parent b1e3500 commit 9afe409

File tree

23 files changed

+196
-131
lines changed

23 files changed

+196
-131
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_inter_process_communication.asciidoc

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -117,25 +117,57 @@ functions specified in the following section.
117117

118118
=== Inter-process communicable memory
119119

120-
121-
This extension adds new free functions under the `ipc_memory` experimental
122-
namespace.
120+
This extension adds a new type alias `handle_data_t` and a new IPC memory handle
121+
type `handle` under the `ipc_memory` experimental namespace.
123122

124123
```
125124
namespace sycl::ext::oneapi::experimental::ipc_memory {
126125

127-
using handle_data_t = std::vector<std::byte>;
126+
using handle_data_t = sycl::span<const std::byte, dynamic_extent>;
127+
128+
struct handle {
129+
handle_data_t data() const;
130+
};
131+
132+
}
133+
```
134+
135+
|====
136+
a|
137+
[frame=all,grid=none]
138+
!====
139+
a!
140+
[source]
141+
----
142+
handle_data_t data() const;
143+
----
144+
!====
145+
146+
_Preconditions:_ The `put` function has not previously been called with this
147+
handle and the USM device memory associated with this handle has not been freed.
148+
149+
_Returns:_ The handle data associated with the IPC handle object. This data can
150+
be transferred to other processes, but cannot be used to recreate a `handle`
151+
object.
152+
153+
!====
154+
155+
Additionally, this extension adds new free functions under the `ipc_memory`
156+
experimental namespace.
157+
158+
```
159+
namespace sycl::ext::oneapi::experimental::ipc_memory {
128160

129-
handle_data_t get(void *ptr, const sycl::context &ctx);
161+
handle get(void *ptr, const sycl::context &ctx);
130162

131-
handle_data_t get(void *ptr);
163+
handle get(void *ptr);
132164

133-
void put(const handle_data_t &handle_data, const sycl::context &ctx);
165+
void put(handle &ipc_handle, const sycl::context &ctx);
134166

135-
void put(const handle_data_t &handle_data);
167+
void put(handle &ipc_handle);
136168

137169
void *open(const handle_data_t &handle_data, const sycl::context &ctx,
138-
const sycl::device &dev);
170+
const sycl::device &dev);
139171

140172
void *open(const handle_data_t &handle_data, const sycl::device &dev);
141173

@@ -155,7 +187,7 @@ a|
155187
a!
156188
[source]
157189
----
158-
handle_data_t get(void *ptr, const sycl::context &ctx)
190+
handle get(void *ptr, const sycl::context &ctx)
159191
----
160192
!====
161193

@@ -175,7 +207,7 @@ device _D_ does not have `aspect::ext_oneapi_ipc_memory`.
175207
a!
176208
[source]
177209
----
178-
handle_data_t get(void *ptr)
210+
handle get(void *ptr)
179211
----
180212
!====
181213

@@ -192,13 +224,14 @@ return ipc_memory::get(ptr, ctxt);
192224
a!
193225
[source]
194226
----
195-
void put(const handle_data_t &handle_data, const sycl::context &ctx)
227+
void put(handle &ipc_handle, const sycl::context &ctx)
196228
----
197229
!====
198230

199-
_Preconditions:_ `handle_data` is the IPC "handle" to USM device memory that was
231+
_Preconditions:_ `ipc_handle` is the IPC "handle" to USM device memory that was
200232
returned from a call to `get` either in this process or in some other process on
201-
the same system. The USM device memory has not yet been freed in this process.
233+
the same system. The `put` function has not been previously called on the
234+
handle.
202235

203236
_Effects:_ Deallocates resources associated with the handle. These resources are
204237
automatically deallocated when the USM device memory is freed, so it is not
@@ -216,7 +249,7 @@ _{endnote}_]
216249
a!
217250
[source]
218251
----
219-
void put(const handle_data_t &handle_data)
252+
void put(handle &ipc_handle)
220253
----
221254
!====
222255

sycl/include/sycl/ext/oneapi/experimental/ipc_memory.hpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,58 @@
1515
#include <sycl/detail/export.hpp>
1616
#include <sycl/device.hpp>
1717
#include <sycl/platform.hpp>
18+
#include <sycl/sycl_span.hpp>
1819

1920
#include <cstddef>
20-
#include <vector>
2121

2222
namespace sycl {
2323
inline namespace _V1 {
2424

2525
namespace ext::oneapi::experimental::ipc_memory {
2626

27-
using handle_data_t = std::vector<std::byte>;
27+
using handle_data_t = sycl::span<const std::byte, dynamic_extent>;
2828

29-
__SYCL_EXPORT handle_data_t get(void *Ptr, const sycl::context &Ctx);
29+
struct handle {
30+
public:
31+
handle_data_t data() const {
32+
return {reinterpret_cast<std::byte *>(MData), MSize};
33+
}
3034

31-
inline handle_data_t get(void *Ptr) {
35+
private:
36+
handle(void *Data, size_t Size) : MData{Data}, MSize{Size} {}
37+
38+
void *MData;
39+
size_t MSize;
40+
41+
friend handle get(void *Ptr, const sycl::context &Ctx);
42+
friend void put(handle &HandleData, const sycl::context &Ctx);
43+
};
44+
45+
__SYCL_EXPORT handle get(void *Ptr, const sycl::context &Ctx);
46+
47+
inline handle get(void *Ptr) {
3248
sycl::device Dev;
3349
sycl::context Ctx = Dev.get_platform().khr_get_default_context();
3450
return ipc_memory::get(Ptr, Ctx);
3551
}
3652

37-
__SYCL_EXPORT void put(const handle_data_t &HandleData,
38-
const sycl::context &Ctx);
53+
__SYCL_EXPORT void put(handle &HandleData, const sycl::context &Ctx);
3954

40-
inline void put(const handle_data_t &HandleData) {
55+
inline void put(handle &HandleData) {
4156
sycl::device Dev;
4257
sycl::context Ctx = Dev.get_platform().khr_get_default_context();
4358
ipc_memory::put(HandleData, Ctx);
4459
}
4560

46-
__SYCL_EXPORT void *open(const handle_data_t &HandleData,
47-
const sycl::context &Ctx, const sycl::device &Dev);
61+
__SYCL_EXPORT void *open(handle_data_t HandleData, const sycl::context &Ctx,
62+
const sycl::device &Dev);
4863

49-
inline void *open(const handle_data_t &HandleData, const sycl::device &Dev) {
64+
inline void *open(handle_data_t HandleData, const sycl::device &Dev) {
5065
sycl::context Ctx = Dev.get_platform().khr_get_default_context();
5166
return ipc_memory::open(HandleData, Ctx, Dev);
5267
}
5368

54-
inline void *open(const handle_data_t &HandleData) {
69+
inline void *open(handle_data_t HandleData) {
5570
sycl::device Dev;
5671
sycl::context Ctx = Dev.get_platform().khr_get_default_context();
5772
return ipc_memory::open(HandleData, Ctx, Dev);

sycl/source/ipc_memory.cpp

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace sycl {
1616
inline namespace _V1 {
1717
namespace ext::oneapi::experimental::ipc_memory {
1818

19-
__SYCL_EXPORT handle_data_t get(void *Ptr, const sycl::context &Ctx) {
19+
__SYCL_EXPORT handle get(void *Ptr, const sycl::context &Ctx) {
2020
auto CtxImpl = sycl::detail::getSyclObjImpl(Ctx);
2121
sycl::detail::adapter_impl &Adapter = CtxImpl->getAdapter();
2222

@@ -30,42 +30,26 @@ __SYCL_EXPORT handle_data_t get(void *Ptr, const sycl::context &Ctx) {
3030
"Device does not support aspect::ext_oneapi_ipc_memory.");
3131
};
3232

33+
void *HandlePtr = nullptr;
3334
size_t HandleSize = 0;
3435
auto UrRes =
3536
Adapter.call_nocheck<sycl::detail::UrApiKind::urIPCGetMemHandleExp>(
36-
CtxImpl->getHandleRef(), Ptr, nullptr, &HandleSize);
37+
CtxImpl->getHandleRef(), Ptr, &HandlePtr, &HandleSize);
3738
if (UrRes != UR_RESULT_SUCCESS) {
3839
CheckDeviceSupport();
3940
Adapter.checkUrResult(UrRes);
4041
}
41-
42-
handle_data_t Res(HandleSize);
43-
UrRes = Adapter.call_nocheck<sycl::detail::UrApiKind::urIPCGetMemHandleExp>(
44-
CtxImpl->getHandleRef(), Ptr, Res.data(), nullptr);
45-
if (UrRes != UR_RESULT_SUCCESS) {
46-
CheckDeviceSupport();
47-
Adapter.checkUrResult(UrRes);
48-
}
49-
return Res;
42+
return {HandlePtr, HandleSize};
5043
}
5144

52-
__SYCL_EXPORT void put(const handle_data_t &HandleData,
53-
const sycl::context &Ctx) {
54-
// TODO: UMF and UR currently requires the handle data to be non-const, so we
55-
// need to make a copy of the data. Once this has been changed, the copy
56-
// can be removed.
57-
// CMPLRLLVM-71181
58-
// https://github.com/oneapi-src/unified-memory-framework/issues/1536
59-
handle_data_t HandleDataCopy = HandleData;
60-
45+
__SYCL_EXPORT void put(handle &Handle, const sycl::context &Ctx) {
6146
auto CtxImpl = sycl::detail::getSyclObjImpl(Ctx);
62-
sycl::detail::adapter_impl &Adapter = CtxImpl->getAdapter();
63-
Adapter.call<sycl::detail::UrApiKind::urIPCPutMemHandleExp>(
64-
CtxImpl->getHandleRef(), HandleDataCopy.data());
47+
CtxImpl->getAdapter().call<sycl::detail::UrApiKind::urIPCPutMemHandleExp>(
48+
CtxImpl->getHandleRef(), Handle.MData);
6549
}
6650

67-
__SYCL_EXPORT void *open(const handle_data_t &HandleData,
68-
const sycl::context &Ctx, const sycl::device &Dev) {
51+
__SYCL_EXPORT void *open(handle_data_t HandleData, const sycl::context &Ctx,
52+
const sycl::device &Dev) {
6953
if (!Dev.has(aspect::ext_oneapi_ipc_memory))
7054
throw sycl::exception(
7155
sycl::make_error_code(errc::feature_not_supported),
@@ -75,17 +59,17 @@ __SYCL_EXPORT void *open(const handle_data_t &HandleData,
7559
sycl::detail::adapter_impl &Adapter = CtxImpl->getAdapter();
7660

7761
// TODO: UMF and UR currently requires the handle data to be non-const, so we
78-
// need to make a copy of the data. Once this has been changed, the copy
79-
// can be removed.
62+
// need const-cast the data pointer. Once this has been changed, the
63+
// const-cast can be removed.
8064
// CMPLRLLVM-71181
8165
// https://github.com/oneapi-src/unified-memory-framework/issues/1536
82-
handle_data_t HandleDataCopy = HandleData;
66+
std::byte *HandleDataPtr = const_cast<std::byte *>(HandleData.data());
8367

8468
void *Ptr = nullptr;
8569
ur_result_t UrRes =
8670
Adapter.call_nocheck<sycl::detail::UrApiKind::urIPCOpenMemHandleExp>(
8771
CtxImpl->getHandleRef(), getSyclObjImpl(Dev)->getHandleRef(),
88-
HandleDataCopy.data(), HandleDataCopy.size(), &Ptr);
72+
HandleDataPtr, HandleData.size(), &Ptr);
8973
if (UrRes == UR_RESULT_ERROR_INVALID_VALUE)
9074
throw sycl::exception(sycl::make_error_code(errc::invalid),
9175
"HandleData data size does not correspond "
@@ -96,8 +80,7 @@ __SYCL_EXPORT void *open(const handle_data_t &HandleData,
9680

9781
__SYCL_EXPORT void close(void *Ptr, const sycl::context &Ctx) {
9882
auto CtxImpl = sycl::detail::getSyclObjImpl(Ctx);
99-
sycl::detail::adapter_impl &Adapter = CtxImpl->getAdapter();
100-
Adapter.call<sycl::detail::UrApiKind::urIPCCloseMemHandleExp>(
83+
CtxImpl->getAdapter().call<sycl::detail::UrApiKind::urIPCCloseMemHandleExp>(
10184
CtxImpl->getHandleRef(), Ptr);
10285
}
10386

sycl/test-e2e/Experimental/ipc_memory.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ int spawner(int argc, char *argv[]) {
4848
{
4949
// Write handle data to file.
5050
{
51-
syclexp::ipc_memory::handle_data_t HandleData =
51+
syclexp::ipc_memory::handle Handle =
5252
syclexp::ipc_memory::get(DataPtr, Q.get_context());
53+
syclexp::ipc_memory::handle_data_t HandleData = Handle.data();
5354
size_t HandleDataSize = HandleData.size();
5455
std::fstream FS(CommsFile, std::ios_base::out | std::ios_base::binary);
5556
FS.write(reinterpret_cast<const char *>(&HandleDataSize), sizeof(size_t));
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// REQUIRES: aspect-usm_device_allocations && aspect-ext_oneapi_ipc_memory
2+
3+
// UNSUPPORTED: level_zero && windows
4+
// UNSUPPORTED-TRACKER: UMFW-348
5+
6+
// RUN: %{build} -o %t.out
7+
// RUN: %{run} %t.out
8+
9+
#include <sycl/detail/core.hpp>
10+
#include <sycl/ext/oneapi/experimental/ipc_memory.hpp>
11+
#include <sycl/usm.hpp>
12+
13+
#include <cstdio>
14+
#include <cstdlib>
15+
16+
#if defined(__linux__)
17+
#include <linux/prctl.h>
18+
#include <sys/prctl.h>
19+
#include <unistd.h>
20+
#endif // defined(__linux__)
21+
22+
namespace syclexp = sycl::ext::oneapi::experimental;
23+
24+
int main() {
25+
sycl::queue Q;
26+
27+
#if defined(__linux__)
28+
// UMF currently requires ptrace permissions to be set for the spawner. As
29+
// such we need to set it until this limitation has been addressed.
30+
// https://github.com/oneapi-src/unified-memory-framework/tree/main?tab=readme-ov-file#level-zero-memory-provider
31+
if (Q.get_backend() == sycl::backend::ext_oneapi_level_zero &&
32+
prctl(PR_SET_PTRACER, getppid()) == -1) {
33+
std::cout << "Failed to set ptracer permissions!" << std::endl;
34+
return 1;
35+
}
36+
#endif // defined(__linux__)
37+
38+
int *DataPtr = sycl::malloc_device<int>(32, Q);
39+
syclexp::ipc_memory::handle Handle =
40+
syclexp::ipc_memory::get(DataPtr, Q.get_context());
41+
42+
// Free data before put.
43+
sycl::free(DataPtr, Q);
44+
45+
// Try calling put after free.
46+
syclexp::ipc_memory::put(Handle, Q.get_context());
47+
48+
return 0;
49+
}

0 commit comments

Comments
 (0)