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

Commit 1d4ed12

Browse files
authored
[SYCL][ESIMD] Add test for simd constructor from an array (#674)
1 parent 8c6a5ff commit 1d4ed12

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+
//==------- ctor_array_core.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, level_zero
9+
// XREQUIRES: gpu
10+
// TODO gpu and level_zero in REQUIRES due to only this platforms supported yet.
11+
// The current "REQUIRES" should be replaced with "gpu" only as mentioned in
12+
// "XREQUIRES".
13+
// UNSUPPORTED: cuda, hip
14+
// RUN: %clangxx -fsycl %s -fsycl-device-code-split=per_kernel -o %t.out
15+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
16+
// TODO Unexpected runtime error "error: unsupported type for load/store" while
17+
// try to use simd::copy_from(), then simd::copy_to() with fixed-size array that
18+
// was defined on device side and the SIMD_RUN_TEST_WITH_VECTOR_LEN_1 macros
19+
// must be enabled when it is resolved.
20+
//
21+
// TODO This test disabled due to simd<short, 32> vector filled with unexpected
22+
// values from 16th element. The issue was created
23+
// https://github.com/intel/llvm/issues/5245 and and the
24+
// SIMD_RUN_TEST_WITH_VECTOR_LEN_32 macros must be enabled when it is resolved.
25+
//
26+
// Test for simd constructor from an array.
27+
// This test uses different data types, dimensionality and different simd
28+
// constructor invocation contexts.
29+
// The test does the following actions:
30+
// - construct fixed-size array that filled with reference values
31+
// - use std::move() to provide it to simd constructor
32+
// - bitwise compare expected and retrieved values
33+
34+
#include "common.hpp"
35+
36+
using namespace esimd_test::api::functional;
37+
using namespace sycl::ext::intel::experimental::esimd;
38+
39+
// Descriptor class for the case of calling constructor in initializer context.
40+
struct initializer {
41+
static std::string get_description() { return "initializer"; }
42+
43+
template <typename DataT, int NumElems>
44+
static void call_simd_ctor(DataT (&&ref_data)[NumElems], DataT *const out) {
45+
static_assert(
46+
type_traits::is_nonconst_rvalue_reference_v<decltype(ref_data)>,
47+
"Provided input data is not nonconst rvalue reference");
48+
const auto simd_by_init = simd<DataT, NumElems>(std::move(ref_data));
49+
simd_by_init.copy_to(out);
50+
}
51+
};
52+
53+
// Descriptor class for the case of calling constructor in variable declaration
54+
// context.
55+
struct var_decl {
56+
static std::string get_description() { return "variable declaration"; }
57+
58+
template <typename DataT, int NumElems>
59+
static void call_simd_ctor(DataT (&&ref_data)[NumElems], DataT *const out) {
60+
static_assert(
61+
type_traits::is_nonconst_rvalue_reference_v<decltype(ref_data)>,
62+
"Provided input data is not nonconst rvalue reference");
63+
const simd<DataT, NumElems> simd_by_var_decl(std::move(ref_data));
64+
simd_by_var_decl.copy_to(out);
65+
}
66+
};
67+
68+
// Descriptor class for the case of calling constructor in rvalue in an
69+
// expression context.
70+
struct rval_in_expr {
71+
static std::string get_description() { return "rvalue in an expression"; }
72+
73+
template <typename DataT, int NumElems>
74+
static void call_simd_ctor(DataT (&&ref_data)[NumElems], DataT *const out) {
75+
static_assert(
76+
type_traits::is_nonconst_rvalue_reference_v<decltype(ref_data)>,
77+
"Provided input data is not nonconst rvalue reference");
78+
simd<DataT, NumElems> simd_by_rval;
79+
simd_by_rval = simd<DataT, NumElems>(std::move(ref_data));
80+
simd_by_rval.copy_to(out);
81+
}
82+
};
83+
84+
// Descriptor class for the case of calling constructor in const reference
85+
// context.
86+
class const_ref {
87+
public:
88+
static std::string get_description() { return "const reference"; }
89+
90+
template <typename DataT, int NumElems>
91+
static void call_simd_ctor(DataT (&&ref_data)[NumElems], DataT *const out) {
92+
static_assert(
93+
type_traits::is_nonconst_rvalue_reference_v<decltype(ref_data)>,
94+
"Provided input data is not nonconst rvalue reference");
95+
call_simd_by_const_ref<DataT, NumElems>(
96+
simd<DataT, NumElems>(std::move(ref_data)), out);
97+
}
98+
99+
private:
100+
template <typename DataT, int NumElems>
101+
static void
102+
call_simd_by_const_ref(const simd<DataT, NumElems> &simd_by_const_ref,
103+
DataT *out) {
104+
simd_by_const_ref.copy_to(out);
105+
}
106+
};
107+
108+
// The main test routine.
109+
// Using functor class to be able to iterate over the pre-defined data types.
110+
template <typename DataT, int NumElems, typename TestCaseT> class run_test {
111+
public:
112+
bool operator()(sycl::queue &queue, const std::string &data_type) {
113+
114+
bool passed = true;
115+
const std::vector<DataT> ref_data = generate_ref_data<DataT, NumElems>();
116+
117+
// If current number of elements is equal to one, then run test with each
118+
// one value from reference data.
119+
// If current number of elements is greater than one, then run tests with
120+
// whole reference data.
121+
if constexpr (NumElems == 1) {
122+
for (size_t i = 0; i < ref_data.size(); ++i) {
123+
passed &= run_verification(queue, {ref_data[i]}, data_type);
124+
}
125+
} else {
126+
passed &= run_verification(queue, ref_data, data_type);
127+
}
128+
return passed;
129+
}
130+
131+
private:
132+
bool run_verification(sycl::queue &queue, const std::vector<DataT> &ref_data,
133+
const std::string &data_type) {
134+
assert(ref_data.size() == NumElems &&
135+
"Reference data size is not equal to the simd vector length.");
136+
137+
bool passed = true;
138+
139+
shared_allocator<DataT> allocator(queue);
140+
shared_vector<DataT> result(NumElems, allocator);
141+
shared_vector<DataT> shared_ref_data(ref_data.begin(), ref_data.end(),
142+
allocator);
143+
144+
queue.submit([&](sycl::handler &cgh) {
145+
const DataT *const ref = shared_ref_data.data();
146+
DataT *const out = result.data();
147+
148+
cgh.single_task<ctors::Kernel<DataT, NumElems, TestCaseT>>(
149+
[=]() SYCL_ESIMD_KERNEL {
150+
DataT ref_on_dev[NumElems];
151+
for (size_t i = 0; i < NumElems; ++i) {
152+
ref_on_dev[i] = ref[i];
153+
}
154+
155+
TestCaseT::template call_simd_ctor<DataT, NumElems>(
156+
std::move(ref_on_dev), out);
157+
});
158+
});
159+
queue.wait_and_throw();
160+
161+
for (size_t i = 0; i < result.size(); ++i) {
162+
if (!are_bitwise_equal(ref_data[i], result[i])) {
163+
passed = false;
164+
165+
const auto description =
166+
ctors::TestDescription<DataT, NumElems, TestCaseT>(
167+
i, result[i], ref_data[i], data_type);
168+
log::fail(description);
169+
}
170+
}
171+
172+
return passed;
173+
}
174+
};
175+
176+
int main(int, char **) {
177+
sycl::queue queue(esimd_test::ESIMDSelector{},
178+
esimd_test::createExceptionHandler());
179+
180+
bool passed = true;
181+
182+
const auto types = get_tested_types<tested_types::all>();
183+
#if defined(SIMD_RUN_TEST_WITH_VECTOR_LEN_1) && \
184+
defined(SIMD_RUN_TEST_WITH_VECTOR_LEN_32)
185+
const auto dims = get_all_dimensions();
186+
#elif SIMD_RUN_TEST_WITH_VECTOR_LEN_32
187+
const auto dims = values_pack<8, 16, 32>();
188+
#elif SIMD_RUN_TEST_WITH_VECTOR_LEN_1
189+
const auto dims = values_pack<1, 8, 16>();
190+
#else
191+
const auto dims = values_pack<8, 16>();
192+
#endif
193+
194+
// Run for specific combinations of types, vector length, and invocation
195+
// contexts.
196+
passed &= for_all_types_and_dims<run_test, initializer>(types, dims, queue);
197+
passed &= for_all_types_and_dims<run_test, var_decl>(types, dims, queue);
198+
passed &= for_all_types_and_dims<run_test, rval_in_expr>(types, dims, queue);
199+
passed &= for_all_types_and_dims<run_test, const_ref>(types, dims, queue);
200+
201+
std::cout << (passed ? "=== Test passed\n" : "=== Test FAILED\n");
202+
return passed ? 0 : 1;
203+
}

0 commit comments

Comments
 (0)