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

Commit 52feaa5

Browse files
authored
[ESIMD] Add test for esimd::merge (#739)
* [ESIMD] Add test for esimd::merge Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent 64c4586 commit 52feaa5

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

SYCL/ESIMD/api/esimd_merge.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//==---------------- esimd_merge.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 %s -o %t.out
11+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
12+
13+
// This is a functional test for esimd::merge free functions, as well as
14+
// two-input version of the simd_obj_impl::merge.
15+
16+
#include "../esimd_test_utils.hpp"
17+
18+
#include <CL/sycl.hpp>
19+
#include <iostream>
20+
#include <sycl/ext/intel/experimental/esimd.hpp>
21+
22+
using namespace sycl::ext::intel::experimental::esimd;
23+
using namespace sycl::ext::intel::experimental;
24+
using namespace cl::sycl;
25+
26+
template <class T> void prn(T *arr, int size, const char *title) {
27+
std::cout << title << ": ";
28+
for (int i = 0; i < size; ++i) {
29+
std::cout << " " << arr[i];
30+
}
31+
std::cout << "\n";
32+
}
33+
34+
int main(void) {
35+
constexpr unsigned VL = 16;
36+
constexpr unsigned FACTOR = 2;
37+
constexpr unsigned SUB_VL = VL / FACTOR / FACTOR;
38+
constexpr unsigned Size = VL * 2;
39+
40+
queue q(esimd_test::ESIMDSelector{}, esimd_test::createExceptionHandler());
41+
42+
auto dev = q.get_device();
43+
std::cout << "Running on " << dev.get_info<info::device::name>() << "\n";
44+
45+
int *A = malloc_shared<int>(Size, q);
46+
int *B = malloc_shared<int>(Size, q);
47+
using MaskElT = typename simd_mask<1>::element_type;
48+
MaskElT *M = malloc_shared<MaskElT>(Size, q);
49+
int *C = malloc_shared<int>(Size, q);
50+
int *C1 = malloc_shared<int>(Size, q);
51+
constexpr int VAL0 = 0;
52+
constexpr int VAL1 = 1;
53+
constexpr int VAL2 = 3;
54+
55+
for (int i = 0; i < Size; ++i) {
56+
A[i] = i % 2 + VAL1; // 1212 ...
57+
B[i] = i % 2 + VAL2; // 3434 ...
58+
// mask out first half of sub-vector, alternating '1' and '2' as 'enabled'
59+
// bit representation in a mask element:
60+
M[i] = (i % SUB_VL) >= (SUB_VL / 2) ? (i % SUB_VL - 1) : 0; // 00120012 ...
61+
C[i] = VAL0;
62+
C1[i] = VAL0;
63+
}
64+
65+
try {
66+
auto e = q.submit([&](handler &cgh) {
67+
cgh.parallel_for<class Test>(Size, [=](id<1> i) SYCL_ESIMD_KERNEL {
68+
simd<int, VL> va(A + i * VL);
69+
simd<int, VL> vb(B + i * VL);
70+
simd_mask<SUB_VL> m(M + i * VL);
71+
// va: 1212121212121212
72+
// vb: 3434343434343434
73+
// m: 0012001200120012
74+
// va.sel.sel: 1111
75+
// vb.sel.sel: 4444
76+
// vc: 4411
77+
simd<int, SUB_VL> vc =
78+
esimd::merge(va.select<SUB_VL * 2, 2>(0).select<SUB_VL, 1>(1),
79+
vb.select<SUB_VL * 1, 2>(1).select<SUB_VL, 1>(0), m);
80+
vc.copy_to(C + i * VL);
81+
82+
// also check that
83+
// vc = esimd::merge(a, b, m)
84+
// is equivalent to
85+
// vc.merge(a, b, m)
86+
simd<int, SUB_VL> vc1;
87+
vc1.merge(va.select<SUB_VL * 2, 2>(0).select<SUB_VL, 1>(1).read(),
88+
vb.select<SUB_VL * 1, 2>(1).select<SUB_VL, 1>(0).read(), m);
89+
vc1.copy_to(C1 + i * VL);
90+
});
91+
});
92+
e.wait();
93+
} catch (sycl::exception const &e) {
94+
std::cout << "SYCL exception caught: " << e.what() << '\n';
95+
sycl::free(A, q);
96+
sycl::free(B, q);
97+
sycl::free(C, q);
98+
sycl::free(C1, q);
99+
sycl::free(M, q);
100+
return 1;
101+
}
102+
103+
int err_cnt = 0;
104+
105+
prn(A, Size, "A");
106+
prn(B, Size, "B");
107+
prn(M, Size, "M");
108+
prn(C, Size, "C");
109+
110+
for (int i = 0; i < Size; ++i) {
111+
int j = i % VL;
112+
int gold =
113+
j >= SUB_VL ? VAL0 : ((j % SUB_VL) >= (SUB_VL / 2) ? VAL1 : VAL2 + 1);
114+
115+
if (C[i] != gold) {
116+
if (++err_cnt < 10) {
117+
std::cout << "(esimd::merge) failed at index " << i << ", " << C[i]
118+
<< " != " << gold << " (gold)\n";
119+
}
120+
}
121+
if (C1[i] != gold) {
122+
if (++err_cnt < 10) {
123+
std::cout << "(simd::merge) failed at index " << i << ", " << C1[i]
124+
<< " != " << gold << " (gold)\n";
125+
}
126+
}
127+
}
128+
if (err_cnt > 0) {
129+
std::cout << " pass rate: "
130+
<< ((float)(Size - err_cnt) / (float)Size) * 100.0f << "% ("
131+
<< (Size - err_cnt) << "/" << Size << ")\n";
132+
}
133+
134+
sycl::free(A, q);
135+
sycl::free(B, q);
136+
sycl::free(C, q);
137+
sycl::free(C1, q);
138+
sycl::free(M, q);
139+
std::cout << (err_cnt > 0 ? "FAILED\n" : "Passed\n");
140+
return err_cnt > 0 ? 1 : 0;
141+
}

0 commit comments

Comments
 (0)