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

Commit 935e810

Browse files
authored
[SYCL][ESIMD] Add simd::copy* E2E tests. (#236)
Signed-off-by: kbobrovs <[email protected]>
1 parent 8300059 commit 935e810

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

SYCL/ESIMD/api/simd_memory_access.cpp

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
//==------- simd_memory_access.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
10+
// RUN: %clangxx -fsycl %s -o %t.out
11+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
12+
//
13+
// The test checks functionality of the memory access APIs which are members of
14+
// the simd class.
15+
16+
#include "../esimd_test_utils.hpp"
17+
18+
#include <CL/sycl.hpp>
19+
#include <sycl/ext/intel/experimental/esimd.hpp>
20+
21+
#include <iostream>
22+
23+
using namespace cl::sycl;
24+
using namespace sycl::ext::intel::experimental::esimd;
25+
26+
template <typename T>
27+
using Acc =
28+
accessor<T, 1, access_mode::read_write, access::target::global_buffer>;
29+
30+
template <typename T, int N, bool IsAcc> struct Kernel;
31+
32+
// Accessor-based kernel.
33+
template <typename T, int N> struct Kernel<T, N, true> {
34+
Acc<T> acc;
35+
Kernel(Acc<T> acc) : acc(acc) {}
36+
37+
void operator()(id<1> i) const SYCL_ESIMD_KERNEL {
38+
const uint32_t ii = static_cast<uint32_t>(i.get(0));
39+
simd<T, N> v;
40+
const auto offset = ii * sizeof(v);
41+
v.copy_from(acc, offset);
42+
v += simd<T, N>(ii * N, 1);
43+
v.copy_to(acc, offset);
44+
}
45+
};
46+
47+
// Pointer-based kernel.
48+
template <typename T, int N> struct Kernel<T, N, false> {
49+
T *ptr;
50+
Kernel(T *ptr) : ptr(ptr) {}
51+
52+
void operator()(id<1> i) const SYCL_ESIMD_KERNEL {
53+
const uint32_t ii = static_cast<uint32_t>(i.get(0));
54+
simd<T, N> v;
55+
const auto offset = ii * (sizeof(v) / sizeof(T));
56+
v.copy_from(ptr + offset);
57+
v += simd<T, N>(ii * N, 1);
58+
v.copy_to(ptr + offset);
59+
}
60+
};
61+
62+
template <typename T> struct char_to_int {
63+
using type = typename std::conditional<
64+
sizeof(T) == 1,
65+
typename std::conditional<std::is_signed<T>::value, int, unsigned>::type,
66+
T>::type;
67+
};
68+
69+
template <bool IsAcc, typename T> void free_mem(T *ptr, sycl::queue q) {
70+
if constexpr (IsAcc) {
71+
delete[] ptr;
72+
} else {
73+
sycl::free(ptr, q);
74+
}
75+
}
76+
77+
// The main test routine.
78+
template <typename T, int N, bool IsAcc> bool test(queue q, size_t size) {
79+
std::cout << "Testing T=" << typeid(T).name() << ", N=" << N
80+
<< " using accessor=" << IsAcc << "...\n";
81+
T *A;
82+
if constexpr (IsAcc) {
83+
A = new T[size];
84+
} else {
85+
A = reinterpret_cast<T *>(sycl::malloc_shared(size, q));
86+
}
87+
88+
for (unsigned i = 0; i < size; ++i) {
89+
A[i] = i; // should not be zero to test `copy_from` really works
90+
}
91+
92+
try {
93+
if constexpr (IsAcc) {
94+
buffer<T, 1> buf(A, range<1>(size));
95+
range<1> glob_range{size / N};
96+
97+
auto e = q.submit([&](handler &cgh) {
98+
auto acc = buf.template get_access<access::mode::read_write>(cgh);
99+
Kernel<T, N, true> kernel(acc);
100+
cgh.parallel_for(glob_range, kernel);
101+
});
102+
} else {
103+
range<1> glob_range{size / N};
104+
105+
auto e = q.submit([&](handler &cgh) {
106+
Kernel<T, N, false> kernel(A);
107+
cgh.parallel_for(glob_range, kernel);
108+
});
109+
}
110+
q.wait_and_throw();
111+
} catch (cl::sycl::exception const &e) {
112+
std::cout << "SYCL exception caught: " << e.what() << '\n';
113+
free_mem<IsAcc>(A, q);
114+
return e.get_cl_code();
115+
}
116+
117+
int err_cnt = 0;
118+
119+
for (unsigned i = 0; i < size; ++i) {
120+
T gold = (T)(i * 2);
121+
T val = A[i];
122+
123+
if (val != gold) {
124+
if (++err_cnt < 10) {
125+
using T1 = typename char_to_int<T>::type;
126+
std::cout << "failed at index " << i << ": " << (T1)val
127+
<< " != " << (T1)gold << " (gold)\n";
128+
}
129+
}
130+
}
131+
if (err_cnt > 0) {
132+
std::cout << " pass rate: "
133+
<< ((float)(size - err_cnt) / (float)size) * 100.0f << "% ("
134+
<< (size - err_cnt) << "/" << size << ")\n";
135+
}
136+
137+
free_mem<IsAcc>(A, q);
138+
139+
std::cout << (err_cnt > 0 ? " FAILED\n" : " Passed\n");
140+
return err_cnt > 0 ? false : true;
141+
}
142+
143+
int main(int argc, char **argv) {
144+
size_t size = 32 * 7;
145+
146+
if (argc > 1) {
147+
size = atoi(argv[1]);
148+
size = size == 0 ? 128 : size;
149+
}
150+
if (size % 32 != 0) {
151+
std::cerr << "*** ERROR: size (" << size << ") must be a multiple of 32\n";
152+
return 2;
153+
}
154+
std::cout << "Using size=" << size << "\n";
155+
queue q(esimd_test::ESIMDSelector{}, esimd_test::createExceptionHandler());
156+
157+
auto dev = q.get_device();
158+
std::cout << "Running on " << dev.get_info<info::device::name>() << "\n";
159+
160+
bool passed = true;
161+
passed &= test<char, 32, true>(q, size);
162+
passed &= test<unsigned char, 16, true>(q, size);
163+
passed &= test<short, 32, true>(q, size);
164+
passed &= test<short, 16, true>(q, size);
165+
passed &= test<unsigned short, 8, true>(q, size);
166+
passed &= test<int, 32, true>(q, size);
167+
passed &= test<unsigned int, 32, true>(q, size);
168+
passed &= test<float, 32, true>(q, size);
169+
170+
passed &= test<char, 32, false>(q, size);
171+
passed &= test<unsigned char, 16, false>(q, size);
172+
passed &= test<short, 32, false>(q, size);
173+
passed &= test<short, 16, false>(q, size);
174+
passed &= test<unsigned short, 8, false>(q, size);
175+
passed &= test<int, 32, false>(q, size);
176+
passed &= test<unsigned int, 32, false>(q, size);
177+
passed &= test<float, 32, false>(q, size);
178+
179+
std::cout << (passed ? "=== Test passed\n" : "=== Test FAILED\n");
180+
return passed ? 0 : 1;
181+
}

0 commit comments

Comments
 (0)