Skip to content

Commit e04ea75

Browse files
author
Sergey Kanaev
committed
[SYCL] Add test
Signed-off-by: Sergey Kanaev <[email protected]>
1 parent cea1bf9 commit e04ea75

File tree

1 file changed

+203
-0
lines changed

1 file changed

+203
-0
lines changed
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t.out %threads_lib
2+
// RUN: %CPU_RUN_PLACEHOLDER SYCL_PI_TRACE=-1 %t.out 2>&1 %CPU_CHECK_PLACEHOLDER
3+
// RUN: %GPU_RUN_PLACEHOLDER SYCL_PI_TRACE=-1 %t.out 2>&1 %GPU_CHECK_PLACEHOLDER
4+
// RUN: %ACC_RUN_PLACEHOLDER SYCL_PI_TRACE=-1 %t.out 2>&1 %ACC_CHECK_PLACEHOLDER
5+
// XFAIL: *
6+
7+
#include <atomic>
8+
#include <condition_variable>
9+
#include <future>
10+
#include <mutex>
11+
#include <thread>
12+
13+
#include <CL/sycl.hpp>
14+
15+
namespace S = cl::sycl;
16+
17+
struct Context {
18+
std::atomic_bool Flag;
19+
S::queue &Queue;
20+
S::buffer<int, 1> Buf1;
21+
S::buffer<int, 1> Buf2;
22+
S::buffer<int, 1> Buf3;
23+
std::mutex Mutex;
24+
std::condition_variable CV;
25+
};
26+
27+
void Thread1Fn(Context *Ctx) {
28+
// 0. initialize resulting buffer with apriori wrong result
29+
{
30+
S::accessor<int, 1, S::access::mode::write,
31+
S::access::target::host_buffer>
32+
Acc(Ctx->Buf2);
33+
34+
for (size_t Idx = 0; Idx < Acc.get_count(); ++Idx)
35+
Acc[Idx] = -1;
36+
}
37+
38+
{
39+
S::accessor<int, 1, S::access::mode::write,
40+
S::access::target::host_buffer>
41+
Acc(Ctx->Buf2);
42+
43+
for (size_t Idx = 0; Idx < Acc.get_count(); ++Idx)
44+
Acc[Idx] = -2;
45+
}
46+
47+
{
48+
S::accessor<int, 1, S::access::mode::write,
49+
S::access::target::host_buffer>
50+
Acc(Ctx->Buf3);
51+
52+
for (size_t Idx = 0; Idx < Acc.get_count(); ++Idx)
53+
Acc[Idx] = -3;
54+
}
55+
56+
// 1. submit task writing to buffer 1
57+
Ctx->Queue.submit([&](S::handler &CGH) {
58+
S::accessor<int, 1, S::access::mode::write,
59+
S::access::target::global_buffer>
60+
GeneratorAcc(Ctx->Buf1, CGH);
61+
62+
auto GeneratorKernel = [GeneratorAcc]() {
63+
for (size_t Idx = 0; Idx < GeneratorAcc.get_count(); ++Idx)
64+
GeneratorAcc[Idx] = Idx;
65+
};
66+
67+
CGH.single_task<class GeneratorTask>(GeneratorKernel);
68+
});
69+
70+
// 2. submit host task writing from buf 1 to buf 2
71+
auto HostTaskEvent = Ctx->Queue.submit([&](S::handler &CGH) {
72+
S::accessor<int, 1, S::access::mode::read,
73+
S::access::target::host_buffer>
74+
CopierSrcAcc(Ctx->Buf1, CGH);
75+
S::accessor<int, 1, S::access::mode::write,
76+
S::access::target::host_buffer>
77+
CopierDstAcc(Ctx->Buf2, CGH);
78+
79+
auto CopierHostTask = [CopierSrcAcc, CopierDstAcc, &Ctx](S::interop_handle IH) {
80+
// TODO write through interop handle objects
81+
//(void)IH.get_native_mem(CopierSrcAcc);
82+
//(void)IH.get_native_mem(CopierDstAcc);
83+
(void)IH.get_native_queue();
84+
(void)IH.get_native_device();
85+
(void)IH.get_native_context();
86+
for (size_t Idx = 0; Idx < CopierDstAcc.get_count(); ++Idx)
87+
CopierDstAcc[Idx] = CopierSrcAcc[Idx];
88+
89+
bool Expected = false;
90+
bool Desired = true;
91+
assert(Ctx->Flag.compare_exchange_strong(Expected, Desired));
92+
93+
{
94+
std::lock_guard<std::mutex> Lock(Ctx->Mutex);
95+
Ctx->CV.notify_all();
96+
}
97+
};
98+
99+
CGH.codeplay_host_task(CopierHostTask);
100+
});
101+
102+
// 3. submit simple task to move data between two buffers
103+
Ctx->Queue.submit([&](S::handler &CGH) {
104+
S::accessor<int, 1, S::access::mode::read,
105+
S::access::target::global_buffer>
106+
SrcAcc(Ctx->Buf2, CGH);
107+
S::accessor<int, 1, S::access::mode::write,
108+
S::access::target::global_buffer>
109+
DstAcc(Ctx->Buf3, CGH);
110+
111+
CGH.depends_on(HostTaskEvent);
112+
113+
auto CopierKernel = [SrcAcc, DstAcc]() {
114+
for (size_t Idx = 0; Idx < DstAcc.get_count(); ++Idx)
115+
DstAcc[Idx] = SrcAcc[Idx];
116+
};
117+
118+
CGH.single_task<class CopierTask>(CopierKernel);
119+
});
120+
121+
// 4. check data in buffer #3
122+
{
123+
S::accessor<int, 1, S::access::mode::read,
124+
S::access::target::host_buffer>
125+
Acc(Ctx->Buf3);
126+
127+
bool Failure = false;
128+
129+
for (size_t Idx = 0; Idx < Acc.get_count(); ++Idx) {
130+
fprintf(stderr, "Third buffer [%3zu] = %i\n", Idx, Acc[Idx]);
131+
132+
Failure |= (Acc[Idx] != Idx);
133+
}
134+
135+
assert(!Failure && "Invalid data in third buffer");
136+
}
137+
}
138+
139+
void Thread2Fn(Context *Ctx) {
140+
std::unique_lock<std::mutex> Lock(Ctx->Mutex);
141+
142+
// T2.1. Wait until flag F is set eq true.
143+
Ctx->CV.wait(Lock, [&Ctx] { return Ctx->Flag.load(); });
144+
145+
assert(Ctx->Flag.load());
146+
}
147+
148+
void test() {
149+
auto EH = [](S::exception_list EL) {
150+
for (const std::exception_ptr &E : EL) {
151+
throw E;
152+
}
153+
};
154+
155+
S::queue Queue(EH);
156+
157+
Context Ctx{{false}, Queue, {10}, {10}, {10}, {}, {}};
158+
159+
// 0. setup: thread 1 T1: exec smth; thread 2 T2: waits; init flag F = false
160+
auto A1 = std::async(std::launch::async, Thread1Fn, &Ctx);
161+
auto A2 = std::async(std::launch::async, Thread2Fn, &Ctx);
162+
163+
A1.get();
164+
A2.get();
165+
166+
assert(Ctx.Flag.load());
167+
168+
// 3. check via host accessor that buf 2 contains valid data
169+
{
170+
S::accessor<int, 1, S::access::mode::read,
171+
S::access::target::host_buffer>
172+
ResultAcc(Ctx.Buf2);
173+
174+
bool failure = false;
175+
for (size_t Idx = 0; Idx < ResultAcc.get_count(); ++Idx) {
176+
fprintf(stderr, "Second buffer [%3zu] = %i\n", Idx, ResultAcc[Idx]);
177+
178+
failure |= (ResultAcc[Idx] != Idx);
179+
}
180+
181+
assert(!failure && "Invalid data in result buffer");
182+
}
183+
}
184+
185+
int main() {
186+
test();
187+
188+
return 0;
189+
}
190+
191+
// launch of GeneratorTask kernel
192+
// CHECK:---> piKernelCreate(
193+
// CHECK: GeneratorTask
194+
// CHECK:---> piEnqueueKernelLaunch(
195+
// prepare for host task
196+
// CHECK:---> piEnqueueMemBufferMap(
197+
// launch of CopierTask kernel
198+
// CHECK:---> piKernelCreate(
199+
// CHECK: CopierTask
200+
// CHECK:---> piEnqueueKernelLaunch(
201+
// TODO need to check for piEventsWait as "wait on dependencies of host task".
202+
// At the same time this piEventsWait may occur anywhere after
203+
// piEnqueueMemBufferMap ("prepare for host task").

0 commit comments

Comments
 (0)