Skip to content

Commit 2df6194

Browse files
committed
[SYCL][Docs] Allow copy-construction of device_global
This commit makes it possible to copy-construct device_global variables if they do not have the device_image_scope property. The restriction on device_image_scope is due to static construction not being allowed in device code, which they would require, while other device_globals have USM storage which will be initialized by the host code, so the constructor on the device is a simple zero-initialization. Signed-off-by: Larsen, Steffen <[email protected]>
1 parent 07bf3c1 commit 2df6194

File tree

4 files changed

+87
-4
lines changed

4 files changed

+87
-4
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_device_global.asciidoc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ public:
244244
device_global() = default;
245245
#endif // __cpp_consteval
246246
247-
device_global(const device_global &) = delete;
247+
// Available if has_property<device_image_scope> is false
248+
constexpr device_global(const device_global &other);
249+
248250
device_global(const device_global &&) = delete;
249251
device_global &operator=(const device_global &) = delete;
250252
device_global &operator=(const device_global &&) = delete;
@@ -324,6 +326,21 @@ The object of type `T` is initialized from the `args` parameter pack using list
324326

325327
`T` must be trivially destructible.
326328

329+
// --- ROW BREAK ---
330+
a|
331+
[source,c++]
332+
----
333+
constexpr device_global(const device_global &other);
334+
----
335+
|
336+
Available if `has_property<device_image_scope> == false`.
337+
338+
Constructs a `device_global` object, and implicit storage for `T` in the global address space on each device that may access it.
339+
340+
The storage on each device for `T` is initialized with a copy of the storage in `other`.
341+
342+
`T` must be copy constructible and trivially destructible.
343+
327344
// --- ROW BREAK ---
328345
a|
329346
[source,c++]

sycl/include/sycl/ext/oneapi/device_global/device_global.hpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ class device_global_base {
7171
device_global_base() = default;
7272
#endif // __cpp_consteval
7373

74+
#ifndef __SYCL_DEVICE_ONLY__
75+
constexpr device_global_base(const device_global_base &DGB)
76+
: init_val{DGB.init_val} {}
77+
#else
78+
constexpr device_global_base(const device_global_base &) {}
79+
#endif // __SYCL_DEVICE_ONLY__
80+
7481
template <access::decorated IsDecorated>
7582
multi_ptr<T, access::address_space::global_space, IsDecorated>
7683
get_multi_ptr() noexcept {
@@ -108,6 +115,8 @@ class device_global_base<
108115
device_global_base() = default;
109116
#endif // __cpp_consteval
110117

118+
constexpr device_global_base(const device_global_base &) = delete;
119+
111120
template <access::decorated IsDecorated>
112121
multi_ptr<T, access::address_space::global_space, IsDecorated>
113122
get_multi_ptr() noexcept {
@@ -151,6 +160,7 @@ class
151160
: public detail::device_global_base<T, detail::properties_t<Props...>> {
152161

153162
using property_list_t = detail::properties_t<Props...>;
163+
using base_t = detail::device_global_base<T, property_list_t>;
154164

155165
public:
156166
using element_type = std::remove_extent_t<T>;
@@ -167,10 +177,11 @@ class
167177
"Property list is invalid.");
168178

169179
// Inherit the base class' constructors
170-
using detail::device_global_base<
171-
T, detail::properties_t<Props...>>::device_global_base;
180+
using detail::device_global_base<T, property_list_t>::device_global_base;
181+
182+
constexpr device_global(const device_global &DG)
183+
: base_t(static_cast<const base_t &>(DG)) {}
172184

173-
device_global(const device_global &) = delete;
174185
device_global(const device_global &&) = delete;
175186
device_global &operator=(const device_global &) = delete;
176187
device_global &operator=(const device_global &&) = delete;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %{build} -std=c++23 -o %t.out
2+
// RUN: %{run} %t.out
3+
//
4+
// The OpenCL GPU backends do not currently support device_global backend
5+
// calls.
6+
// UNSUPPORTED: opencl && gpu
7+
//
8+
// Tests the copy ctor on device_global without device_image_scope.
9+
10+
#include <sycl/detail/core.hpp>
11+
12+
namespace oneapiext = sycl::ext::oneapi::experimental;
13+
14+
oneapiext::device_global<const int> DGInit{3};
15+
oneapiext::device_global<const int> DGCopy{DGInit};
16+
17+
int main() {
18+
sycl::queue Q;
19+
20+
int ReadVals[2] = {0, 0};
21+
{
22+
sycl::buffer<int, 1> ReadValsBuff{ReadVals, 2};
23+
24+
Q.submit([&](sycl::handler &CGH) {
25+
sycl::accessor ReadValsAcc{ReadValsBuff, CGH, sycl::write_only};
26+
CGH.single_task([=]() {
27+
ReadValsAcc[0] = DGInit.get();
28+
ReadValsAcc[1] = DGCopy.get();
29+
});
30+
}).wait_and_throw();
31+
}
32+
33+
assert(ReadVals[0] == 3);
34+
assert(ReadVals[1] == 3);
35+
36+
return 0;
37+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %clangxx -std=c++23 -fsycl -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note %s
2+
//
3+
// Tests that the copy ctor on device_global with device_image_scope is
4+
// unavailable.
5+
6+
#include <sycl/sycl.hpp>
7+
8+
namespace oneapiext = sycl::ext::oneapi::experimental;
9+
10+
using device_image_properties =
11+
decltype(oneapiext::properties{oneapiext::device_image_scope});
12+
13+
oneapiext::device_global<const int, device_image_properties> DGInit{3};
14+
oneapiext::device_global<const int, device_image_properties> DGCopy{DGInit};
15+
16+
// expected-error@sycl/ext/oneapi/device_global/device_global.hpp:* {{call to deleted constructor}}
17+
18+
int main() { return 0; }

0 commit comments

Comments
 (0)