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

Commit 3b3e023

Browse files
committed
[SYCL] add function pointer tests
1 parent 9a5a35f commit 3b3e023

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// UNSUPPORTED: windows
2+
// UNSUPPORTED: cuda || level_zero
3+
// CUDA does not support the function pointer as kernel argument extension.
4+
// Hangs on level zero
5+
6+
// RUN: %clangxx -Xclang -fsycl-allow-func-ptr -std=c++14 -fsycl %s -o %t.out
7+
// RUN: %HOST_RUN_PLACEHOLDER %t.out
8+
// RUN: %CPU_RUN_PLACEHOLDER %t.out
9+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
10+
// FIXME: This test should use runtime early exit once correct check for
11+
// corresponding extension is implemented
12+
13+
#include <CL/sycl.hpp>
14+
15+
#include <algorithm>
16+
#include <iostream>
17+
#include <vector>
18+
19+
[[intel::device_indirectly_callable]] extern "C" int add(int A, int B) {
20+
return A + B;
21+
}
22+
23+
int main() {
24+
const int Size = 10;
25+
std::vector<long> A(Size, 1);
26+
std::vector<long> B(Size, 2);
27+
28+
cl::sycl::queue Q;
29+
cl::sycl::device D = Q.get_device();
30+
cl::sycl::context C = Q.get_context();
31+
cl::sycl::program P(C);
32+
33+
P.build_with_kernel_type<class K>();
34+
cl::sycl::kernel KE = P.get_kernel<class K>();
35+
36+
auto FptrStorage = cl::sycl::ONEAPI::get_device_func_ptr(&add, "add", P, D);
37+
if (!D.is_host()) {
38+
// FIXME: update this check with query to supported extension
39+
// For now, we don't have runtimes that report required OpenCL extension and
40+
// it is hard to understand should this functionality be supported or not.
41+
// So, let's skip this test if FptrStorage is 0, which means that by some
42+
// reason we failed to obtain device function pointer. Just to avoid false
43+
// alarms
44+
if (0 == FptrStorage) {
45+
std::cout << "Test PASSED. (it was actually skipped)" << std::endl;
46+
return 0;
47+
}
48+
}
49+
50+
cl::sycl::buffer<long> BufA(A.data(), cl::sycl::range<1>(Size));
51+
cl::sycl::buffer<long> BufB(B.data(), cl::sycl::range<1>(Size));
52+
53+
Q.submit([&](cl::sycl::handler &CGH) {
54+
auto AccA =
55+
BufA.template get_access<cl::sycl::access::mode::read_write>(CGH);
56+
auto AccB = BufB.template get_access<cl::sycl::access::mode::read>(CGH);
57+
CGH.parallel_for<class K>(
58+
KE, cl::sycl::range<1>(Size), [=](cl::sycl::id<1> Index) {
59+
auto Fptr =
60+
cl::sycl::ONEAPI::to_device_func_ptr<decltype(add)>(FptrStorage);
61+
AccA[Index] = Fptr(AccA[Index], AccB[Index]);
62+
});
63+
});
64+
65+
auto HostAcc = BufA.get_access<cl::sycl::access::mode::read>();
66+
auto *Data = HostAcc.get_pointer();
67+
68+
if (std::all_of(Data, Data + Size, [](long V) { return V == 3; })) {
69+
std::cout << "Test PASSED." << std::endl;
70+
} else {
71+
std::cout << "Test FAILED." << std::endl;
72+
for (int I = 0; I < Size; ++I) {
73+
std::cout << HostAcc[I] << " ";
74+
}
75+
std::cout << std::endl;
76+
}
77+
78+
return 0;
79+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// UNSUPPORTED: windows
2+
// UNSUPPORTED: cuda || level_zero
3+
// CUDA does not support the function pointer as kernel argument extension.
4+
// Hangs on level zero
5+
6+
// RUN: %clangxx -Xclang -fsycl-allow-func-ptr -std=c++14 -fsycl %s -o %t.out
7+
// RUN: %HOST_RUN_PLACEHOLDER %t.out
8+
// RUN: %CPU_RUN_PLACEHOLDER %t.out
9+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
10+
// FIXME: This test should use runtime early exit once correct check for
11+
// corresponding extension is implemented
12+
13+
#include <CL/sycl.hpp>
14+
15+
#include <algorithm>
16+
#include <iostream>
17+
#include <vector>
18+
19+
[[intel::device_indirectly_callable]] extern "C" int add(int A, int B) {
20+
return A + B;
21+
}
22+
23+
[[intel::device_indirectly_callable]] extern "C" int sub(int A, int B) {
24+
return A - B;
25+
}
26+
27+
int main() {
28+
const int Size = 10;
29+
30+
cl::sycl::queue Q;
31+
cl::sycl::device D = Q.get_device();
32+
cl::sycl::context C = Q.get_context();
33+
cl::sycl::program P(C);
34+
35+
P.build_with_kernel_type<class K>();
36+
cl::sycl::kernel KE = P.get_kernel<class K>();
37+
38+
cl::sycl::buffer<cl::sycl::ONEAPI::device_func_ptr_holder_t> DispatchTable(2);
39+
{
40+
auto DTAcc =
41+
DispatchTable.get_access<cl::sycl::access::mode::discard_write>();
42+
DTAcc[0] = cl::sycl::ONEAPI::get_device_func_ptr(&add, "add", P, D);
43+
DTAcc[1] = cl::sycl::ONEAPI::get_device_func_ptr(&sub, "sub", P, D);
44+
if (!D.is_host()) {
45+
// FIXME: update this check with query to supported extension
46+
// For now, we don't have runtimes that report required OpenCL extension
47+
// and it is hard to understand should this functionality be supported or
48+
// not. So, let's skip this test if DTAcc[i] is 0, which means that by
49+
// some reason we failed to obtain device function pointer. Just to avoid
50+
// false alarms
51+
if (0 == DTAcc[0] || 0 == DTAcc[1]) {
52+
std::cout << "Test PASSED. (it was actually skipped)" << std::endl;
53+
return 0;
54+
}
55+
}
56+
}
57+
58+
for (int Mode = 0; Mode < 2; ++Mode) {
59+
std::vector<int> A(Size, 1);
60+
std::vector<int> B(Size, 2);
61+
62+
cl::sycl::buffer<int> bufA(A.data(), cl::sycl::range<1>(Size));
63+
cl::sycl::buffer<int> bufB(B.data(), cl::sycl::range<1>(Size));
64+
65+
Q.submit([&](cl::sycl::handler &CGH) {
66+
auto AccA =
67+
bufA.template get_access<cl::sycl::access::mode::read_write>(CGH);
68+
auto AccB = bufB.template get_access<cl::sycl::access::mode::read>(CGH);
69+
auto AccDT =
70+
DispatchTable.template get_access<cl::sycl::access::mode::read>(CGH);
71+
CGH.parallel_for<class K>(
72+
KE, cl::sycl::range<1>(Size), [=](cl::sycl::id<1> Index) {
73+
auto FP = cl::sycl::ONEAPI::to_device_func_ptr<int(int, int)>(
74+
AccDT[Mode]);
75+
76+
AccA[Index] = FP(AccA[Index], AccB[Index]);
77+
});
78+
});
79+
80+
auto HostAcc = bufA.get_access<cl::sycl::access::mode::read>();
81+
82+
int Reference = Mode == 0 ? 3 : -1;
83+
auto *Data = HostAcc.get_pointer();
84+
85+
if (std::all_of(Data, Data + Size,
86+
[=](long V) { return V == Reference; })) {
87+
std::cout << "Test " << Mode << " PASSED." << std::endl;
88+
} else {
89+
std::cout << "Test " << Mode << " FAILED." << std::endl;
90+
for (int I = 0; I < Size; ++I) {
91+
std::cout << HostAcc[I] << " ";
92+
}
93+
std::cout << std::endl;
94+
}
95+
}
96+
97+
return 0;
98+
}

0 commit comments

Comments
 (0)