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

Commit 14e781e

Browse files
authored
[ESIMD] Add ahead-of-time compilation test. (#523)
Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent 0565e79 commit 14e781e

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

SYCL/ESIMD/aot_mixed.cpp

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//==---------------- aot_mixed.cpp - DPC++ ESIMD on-device test -----------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// REQUIRES: gpu
9+
// UNSUPPORTED: cuda || hip
10+
// RUN: %clangxx -fsycl -fsycl-targets=spir64_gen -Xsycl-target-backend=spir64_gen "-device gen9" -o %t.sycl.out -DENABLE_SYCL=0 %s
11+
// RUN: %GPU_RUN_PLACEHOLDER %t.sycl.out
12+
// RUN: %clangxx -fsycl -fsycl-targets=spir64_gen -Xsycl-target-backend=spir64_gen "-device gen9" -o %t.out %s
13+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
14+
// XFAIL: *
15+
// TODO: remove XFAIL once ocloc support for automatic scalar/vector SPIRV
16+
// module dispatching is available in public drivers. Also change 'gen9' (safe
17+
// variant to reliably get unexpected PASS when ocloc is fixed) to '*' (which
18+
// stresses ocloc).
19+
20+
// This test checks ESIMD ahead-of-time compilation scenarios:
21+
// 1) When the application contains both SYCL and ESIMD kernel, thus requiring
22+
// different GPU back-ends (scalar and vector) to kick-in at compile-time.
23+
// 2) When the application contains only ESIMD kernel.
24+
25+
#include "esimd_test_utils.hpp"
26+
27+
#include <CL/sycl.hpp>
28+
#include <iostream>
29+
#include <sycl/ext/intel/experimental/esimd.hpp>
30+
31+
using namespace cl::sycl;
32+
33+
#ifndef ENABLE_SIMD
34+
#define ENABLE_SIMD 1
35+
#endif
36+
37+
#ifndef ENABLE_SYCL
38+
#define ENABLE_SYCL 1
39+
#endif
40+
41+
bool verify(float *A, float *B, float *C, size_t Size) {
42+
int err_cnt = 0;
43+
44+
for (unsigned i = 0; i < Size; ++i) {
45+
if (A[i] + B[i] != C[i]) {
46+
if (++err_cnt < 10) {
47+
std::cout << "failed at index " << i << ", " << C[i] << " != " << A[i]
48+
<< " + " << B[i] << "\n";
49+
}
50+
}
51+
}
52+
if (err_cnt > 0) {
53+
std::cout << " pass rate: "
54+
<< ((float)(Size - err_cnt) / (float)Size) * 100.0f << "% ("
55+
<< (Size - err_cnt) << "/" << Size << ")\n";
56+
}
57+
return err_cnt == 0;
58+
}
59+
60+
constexpr unsigned Size = 1024 * 128;
61+
constexpr unsigned VL = 16;
62+
63+
#if ENABLE_SIMD
64+
bool test_esimd(queue q) {
65+
std::cout << "Running ESIMD kernel...\n";
66+
float *A = new float[Size];
67+
float *B = new float[Size];
68+
float *C = new float[Size];
69+
70+
for (unsigned i = 0; i < Size; ++i) {
71+
A[i] = B[i] = i;
72+
C[i] = 0.0f;
73+
}
74+
75+
try {
76+
buffer<float, 1> bufa(A, range<1>(Size));
77+
buffer<float, 1> bufb(B, range<1>(Size));
78+
buffer<float, 1> bufc(C, range<1>(Size));
79+
80+
auto e = q.submit([&](handler &cgh) {
81+
auto PA = bufa.get_access<access::mode::read>(cgh);
82+
auto PB = bufb.get_access<access::mode::read>(cgh);
83+
auto PC = bufc.get_access<access::mode::write>(cgh);
84+
cgh.parallel_for<class TestESIMD>(
85+
Size / VL, [=](id<1> i) SYCL_ESIMD_KERNEL {
86+
using namespace sycl::ext::intel::experimental::esimd;
87+
unsigned int offset = i * VL * sizeof(float);
88+
simd<float, VL> va;
89+
va.copy_from(PA, offset);
90+
simd<float, VL> vb;
91+
vb.copy_from(PB, offset);
92+
simd<float, VL> vc = va + vb;
93+
vc.copy_to(PC, offset);
94+
});
95+
});
96+
e.wait();
97+
} catch (cl::sycl::exception const &e) {
98+
std::cout << "SYCL exception caught: " << e.what() << '\n';
99+
100+
delete[] A;
101+
delete[] B;
102+
delete[] C;
103+
104+
return false;
105+
}
106+
bool passed = verify(A, B, C, Size);
107+
108+
delete[] A;
109+
delete[] B;
110+
delete[] C;
111+
return passed;
112+
}
113+
#endif
114+
115+
#if ENABLE_SYCL
116+
bool test_sycl(queue q) {
117+
std::cout << "Running SYCL kernel...\n";
118+
float *A = new float[Size];
119+
float *B = new float[Size];
120+
float *C = new float[Size];
121+
122+
for (unsigned i = 0; i < Size; ++i) {
123+
A[i] = B[i] = i;
124+
C[i] = 0.0f;
125+
}
126+
127+
try {
128+
buffer<float, 1> bufa(A, range<1>(Size));
129+
buffer<float, 1> bufb(B, range<1>(Size));
130+
buffer<float, 1> bufc(C, range<1>(Size));
131+
132+
auto e = q.submit([&](handler &cgh) {
133+
auto PA = bufa.get_access<access::mode::read>(cgh);
134+
auto PB = bufb.get_access<access::mode::read>(cgh);
135+
auto PC = bufc.get_access<access::mode::write>(cgh);
136+
cgh.parallel_for<class TestSYCL>(Size,
137+
[=](id<1> i) { PC[i] = PA[i] + PB[i]; });
138+
});
139+
e.wait();
140+
} catch (cl::sycl::exception const &e) {
141+
std::cout << "SYCL exception caught: " << e.what() << '\n';
142+
143+
delete[] A;
144+
delete[] B;
145+
delete[] C;
146+
147+
return false;
148+
}
149+
bool passed = verify(A, B, C, Size);
150+
151+
delete[] A;
152+
delete[] B;
153+
delete[] C;
154+
return passed;
155+
}
156+
#endif
157+
158+
int main(void) {
159+
queue q(esimd_test::ESIMDSelector{}, esimd_test::createExceptionHandler());
160+
auto dev = q.get_device();
161+
std::cout << "Running on " << dev.get_info<info::device::name>() << "\n";
162+
163+
bool passed = true;
164+
#if ENABLE_SIMD
165+
passed &= test_esimd(q);
166+
#endif
167+
#if ENABLE_SYCL
168+
passed &= test_sycl(q);
169+
#endif
170+
171+
std::cout << (passed ? "TEST Passed\n" : "TEST FAILED\n");
172+
return passed ? 0 : 1;
173+
}

0 commit comments

Comments
 (0)