Skip to content
This repository was archived by the owner on Mar 28, 2023. It is now read-only.

Commit da1df22

Browse files
authored
[SYCL] Adds extensive testing for SYCL 2020 implicitly device copyable types. (#1583)
Signed-off-by: Maronas, Marcos <[email protected]>
1 parent 4ce05a0 commit da1df22

File tree

1 file changed

+376
-0
lines changed

1 file changed

+376
-0
lines changed
Lines changed: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t.out
2+
// RUN: %CPU_RUN_PLACEHOLDER %t.out
3+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
4+
// RUN: %ACC_RUN_PLACEHOLDER %t.out
5+
6+
//==--device_implicitly_copyable.cpp - SYCL implicit device copyable test --==//
7+
//
8+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
9+
// See https://llvm.org/LICENSE.txt for license information.
10+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11+
//
12+
//===----------------------------------------------------------------------===//
13+
#include <cassert>
14+
#include <iostream>
15+
16+
#include <sycl/sycl.hpp>
17+
18+
struct ACopyable {
19+
int i;
20+
ACopyable() = default;
21+
ACopyable(int _i) : i(_i) {}
22+
ACopyable(const ACopyable &x) : i(x.i) {}
23+
};
24+
25+
template <> struct sycl::is_device_copyable<ACopyable> : std::true_type {};
26+
27+
template <typename DataT, size_t ArrSize>
28+
void CaptureAndCopy(const DataT *data_arr, const DataT &data_scalar,
29+
DataT *result_arr, DataT *result_scalar, sycl::queue &q) {
30+
// We need to copy data_arr, otherwise when using a device it tries to use the host memory
31+
DataT cpy_data_arr[ArrSize];
32+
std::memcpy(cpy_data_arr, data_arr, sizeof(cpy_data_arr));
33+
sycl::buffer<DataT, 1> buf_arr{result_arr, sycl::range<1>(ArrSize)};
34+
sycl::buffer<DataT, 1> buf_scalar{result_scalar, sycl::range<1>(1)};
35+
36+
q.submit([&](sycl::handler &cgh) {
37+
auto acc_arr = sycl::accessor{buf_arr, cgh, sycl::read_write};
38+
auto acc_scalar = sycl::accessor{buf_scalar, cgh, sycl::read_write};
39+
cgh.single_task([=]() {
40+
for (auto i = 0; i < ArrSize; i++) {
41+
acc_arr[i] = cpy_data_arr[i];
42+
}
43+
acc_scalar[0] = data_scalar;
44+
});
45+
});
46+
}
47+
48+
int main() {
49+
constexpr size_t arr_size = 5;
50+
constexpr int ref_val = 14;
51+
sycl::queue q;
52+
{
53+
using DataT = std::pair<int, float>;
54+
DataT pair_arr[arr_size];
55+
DataT pair{ref_val, ref_val};
56+
DataT result_pair_arr[arr_size];
57+
DataT result_pair;
58+
59+
for (auto i = 0; i < arr_size; i++) {
60+
pair_arr[i].first = i;
61+
pair_arr[i].second = i;
62+
}
63+
64+
CaptureAndCopy<DataT, arr_size>(pair_arr, pair, result_pair_arr,
65+
&result_pair, q);
66+
67+
for (auto i = 0; i < arr_size; i++) {
68+
assert(result_pair_arr[i].first == i);
69+
assert(result_pair_arr[i].second == i);
70+
}
71+
assert(result_pair.first == ref_val && result_pair.second == ref_val);
72+
}
73+
74+
{
75+
using DataT = std::pair<ACopyable, float>;
76+
DataT pair_arr[arr_size];
77+
DataT pair{ACopyable(ref_val), ref_val};
78+
DataT result_pair_arr[arr_size];
79+
DataT result_pair;
80+
81+
for (auto i = 0; i < arr_size; i++) {
82+
pair_arr[i].first = ACopyable(i);
83+
pair_arr[i].second = i;
84+
}
85+
86+
CaptureAndCopy<DataT, arr_size>(pair_arr, pair, result_pair_arr,
87+
&result_pair, q);
88+
89+
for (auto i = 0; i < arr_size; i++) {
90+
assert(result_pair_arr[i].first.i == i);
91+
assert(result_pair_arr[i].second == i);
92+
}
93+
assert(result_pair.first.i == ref_val && result_pair.second == ref_val);
94+
}
95+
96+
{
97+
using DataT = std::tuple<int, float, bool>;
98+
DataT tuple_arr[arr_size];
99+
DataT tuple{ref_val, ref_val, true};
100+
DataT result_tuple_arr[arr_size];
101+
DataT result_tuple;
102+
103+
for (auto i = 0; i < arr_size; i++) {
104+
auto &t = tuple_arr[i];
105+
std::get<0>(t) = i;
106+
std::get<1>(t) = i;
107+
std::get<2>(t) = true;
108+
}
109+
110+
CaptureAndCopy<DataT, arr_size>(tuple_arr, tuple, result_tuple_arr,
111+
&result_tuple, q);
112+
113+
for (auto i = 0; i < arr_size; i++) {
114+
auto t = result_tuple_arr[i];
115+
assert(std::get<0>(t) == i);
116+
assert(std::get<1>(t) == i);
117+
assert(std::get<2>(t) == true);
118+
}
119+
assert(std::get<0>(result_tuple) == ref_val);
120+
assert(std::get<1>(result_tuple) == ref_val);
121+
assert(std::get<2>(result_tuple) == true);
122+
}
123+
124+
{
125+
using DataT = std::tuple<ACopyable, float, bool>;
126+
DataT tuple_arr[arr_size];
127+
DataT tuple{ACopyable(ref_val), ref_val, true};
128+
DataT result_tuple_arr[arr_size];
129+
DataT result_tuple;
130+
131+
for (auto i = 0; i < arr_size; i++) {
132+
auto &t = tuple_arr[i];
133+
std::get<0>(t) = ACopyable(i);
134+
std::get<1>(t) = i;
135+
std::get<2>(t) = true;
136+
}
137+
138+
CaptureAndCopy<DataT, arr_size>(tuple_arr, tuple, result_tuple_arr,
139+
&result_tuple, q);
140+
141+
for (auto i = 0; i < arr_size; i++) {
142+
auto t = result_tuple_arr[i];
143+
assert(std::get<0>(t).i == i);
144+
assert(std::get<1>(t) == i);
145+
assert(std::get<2>(t) == true);
146+
}
147+
assert(std::get<0>(result_tuple).i == ref_val);
148+
assert(std::get<1>(result_tuple) == ref_val);
149+
assert(std::get<2>(result_tuple) == true);
150+
}
151+
152+
{
153+
using DataT = std::variant<int, float, bool>;
154+
DataT variant_arr[arr_size];
155+
DataT variant{14};
156+
DataT result_variant_arr[arr_size];
157+
DataT result_variant;
158+
159+
constexpr int variant_size = 3;
160+
for (auto i = 0; i < arr_size; i++) {
161+
auto &v = variant_arr[i];
162+
auto index = i % variant_size;
163+
if (index == 0) {
164+
v = i;
165+
} else if (index == 1) {
166+
v = (float)i;
167+
} else {
168+
v = true;
169+
}
170+
}
171+
172+
CaptureAndCopy<DataT, arr_size>(variant_arr, variant, result_variant_arr,
173+
&result_variant, q);
174+
175+
for (auto i = 0; i < arr_size; i++) {
176+
auto v = result_variant_arr[i];
177+
auto index = i % variant_size;
178+
if (index == 0) {
179+
assert(std::get<0>(v) == i);
180+
} else if (index == 1) {
181+
assert(std::get<1>(v) == i);
182+
} else {
183+
assert(std::get<2>(v) == true);
184+
}
185+
}
186+
assert(std::get<0>(result_variant) == ref_val);
187+
}
188+
189+
{
190+
using DataT = std::variant<ACopyable>;
191+
DataT variant_arr[arr_size];
192+
DataT variant;
193+
DataT result_variant_arr[arr_size];
194+
DataT result_variant;
195+
q.submit([&](sycl::handler &cgh) {
196+
cgh.single_task([=]() {
197+
// Some implementations of std::variant with complex types relies on
198+
// virtual functions, so they cannot be used within sycl kernels
199+
auto size = sizeof(variant_arr[0]);
200+
size = sizeof(variant);
201+
});
202+
}).wait_and_throw();
203+
}
204+
205+
{
206+
using DataT = std::array<int, arr_size>;
207+
DataT arr_arr[arr_size];
208+
DataT arr;
209+
DataT result_arr_arr[arr_size];
210+
DataT result_arr;
211+
212+
for (auto i = 0; i < arr_size; i++) {
213+
auto &a = arr_arr[i];
214+
for (auto j = 0; j < arr_size; j++) {
215+
a[j] = j;
216+
}
217+
arr[i] = i;
218+
}
219+
220+
CaptureAndCopy<DataT, arr_size>(arr_arr, arr, result_arr_arr, &result_arr,
221+
q);
222+
223+
for (auto i = 0; i < arr_size; i++) {
224+
auto a = result_arr_arr[i];
225+
for (auto j = 0; j < arr_size; j++) {
226+
assert(a[j] == j);
227+
}
228+
assert(result_arr[i] == i);
229+
}
230+
}
231+
232+
{
233+
using DataT = std::array<ACopyable, arr_size>;
234+
DataT arr_arr[arr_size];
235+
DataT arr;
236+
DataT result_arr_arr[arr_size];
237+
DataT result_arr;
238+
239+
for (auto i = 0; i < arr_size; i++) {
240+
auto &a = arr_arr[i];
241+
for (auto j = 0; j < arr_size; j++) {
242+
a[j] = ACopyable(j);
243+
}
244+
arr[i] = ACopyable(i);
245+
}
246+
247+
CaptureAndCopy<DataT, arr_size>(arr_arr, arr, result_arr_arr, &result_arr,
248+
q);
249+
250+
for (auto i = 0; i < arr_size; i++) {
251+
auto a = result_arr_arr[i];
252+
for (auto j = 0; j < arr_size; j++) {
253+
assert(a[j].i == j);
254+
}
255+
assert(result_arr[i].i == i);
256+
}
257+
}
258+
259+
{
260+
using DataT = std::optional<int>;
261+
DataT opt_arr[arr_size];
262+
DataT opt;
263+
DataT result_opt_arr[arr_size];
264+
DataT result_opt;
265+
266+
for (auto i = 0; i < arr_size; i++) {
267+
opt_arr[i] = i;
268+
}
269+
opt = ref_val;
270+
271+
CaptureAndCopy<DataT, arr_size>(opt_arr, opt, result_opt_arr, &result_opt,
272+
q);
273+
274+
for (auto i = 0; i < arr_size; i++) {
275+
assert(result_opt_arr[i] == i);
276+
}
277+
278+
assert(result_opt == ref_val);
279+
}
280+
281+
{
282+
using DataT = std::optional<ACopyable>;
283+
DataT opt_arr[arr_size];
284+
DataT opt;
285+
DataT result_opt_arr[arr_size];
286+
DataT result_opt;
287+
288+
for (auto i = 0; i < arr_size; i++) {
289+
opt_arr[i] = ACopyable(i);
290+
}
291+
opt = ACopyable(ref_val);
292+
293+
CaptureAndCopy<DataT, arr_size>(opt_arr, opt, result_opt_arr, &result_opt,
294+
q);
295+
296+
for (auto i = 0; i < arr_size; i++) {
297+
assert(result_opt_arr[i]->i == i);
298+
}
299+
300+
assert(result_opt->i == ref_val);
301+
}
302+
303+
{
304+
using DataT = std ::string_view;
305+
std::string strv_arr_val[arr_size];
306+
std::string strv_val{std::to_string(ref_val)};
307+
DataT strv_arr[arr_size];
308+
DataT strv{strv_val};
309+
DataT result_strv_arr[arr_size];
310+
DataT result_strv;
311+
312+
for (auto i = 0; i < arr_size; i++) {
313+
strv_arr_val[i] = std::to_string(i);
314+
strv_arr[i] = std::string_view{strv_arr_val[i]};
315+
}
316+
317+
CaptureAndCopy<DataT, arr_size>(strv_arr, strv, result_strv_arr,
318+
&result_strv, q);
319+
320+
for (auto i = 0; i < arr_size; i++) {
321+
assert(result_strv_arr[i] == std::to_string(i));
322+
}
323+
324+
assert(result_strv == std::to_string(ref_val));
325+
}
326+
327+
#if __cpp_lib_span >= 202002
328+
{
329+
using DataT = std::span<int>;
330+
std::vector<int> v(arr_size);
331+
DataT s_arr[arr_size];
332+
DataT s{v.data(), arr_size};
333+
DataT result_s_arr[arr_size];
334+
DataT result_s{v.data(), arr_size};
335+
336+
for (auto i = 0; i < arr_size; i++) {
337+
s[i] = i;
338+
s_arr[i] = s;
339+
}
340+
341+
CaptureAndCopy<DataT, arr_size>(s_arr, s, result_s_arr, &result_s, q);
342+
343+
for (auto i = 0; i < arr_size; i++) {
344+
assert(result_s[i] == i);
345+
for (auto j = 0; j < arr_size; j++) {
346+
assert(result_s_arr[i][j] == j);
347+
}
348+
}
349+
}
350+
#endif
351+
352+
{
353+
using DataT = sycl::span<int>;
354+
std::vector<int> v(arr_size);
355+
DataT s_arr[arr_size];
356+
DataT s{v.data(), arr_size};
357+
DataT result_s_arr[arr_size];
358+
DataT result_s{v.data(), arr_size};
359+
360+
for (auto i = 0; i < arr_size; i++) {
361+
s[i] = i;
362+
s_arr[i] = s;
363+
}
364+
365+
CaptureAndCopy<DataT, arr_size>(s_arr, s, result_s_arr, &result_s, q);
366+
367+
for (auto i = 0; i < arr_size; i++) {
368+
assert(result_s[i] == i);
369+
for (auto j = 0; j < arr_size; j++) {
370+
assert(result_s_arr[i][j] == j);
371+
}
372+
}
373+
}
374+
375+
std::cout << "Test passed" << std::endl;
376+
}

0 commit comments

Comments
 (0)