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

Commit 1017d07

Browse files
authored
[SYCL][ESIMD] Add tests on simd copy and move assignment operators (#762)
* [SYCL][ESIMD] Add tests on simd copy and move assignment operators
1 parent d98407d commit 1017d07

File tree

12 files changed

+290
-13
lines changed

12 files changed

+290
-13
lines changed

SYCL/ESIMD/api/functional/common.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ template <typename T> bool are_bitwise_equal(T lhs, T rhs) {
4646

4747
} // namespace details
4848

49+
// Class used as a kernel ID.
50+
template <typename DataT, int NumElems, typename T> struct Kernel;
51+
4952
template <typename DataT>
5053
using shared_allocator = sycl::usm_allocator<DataT, sycl::usm::alloc::shared>;
5154

SYCL/ESIMD/api/functional/ctors/common.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717

1818
namespace esimd_test::api::functional::ctors {
1919

20-
// Dummy kernel for submitting some code into device side.
21-
template <typename DataT, int NumElems, typename T> struct Kernel;
22-
2320
template <typename DataT, int NumElems, typename ContextT>
2421
class TestDescription : public ITestDescription {
2522
public:

SYCL/ESIMD/api/functional/ctors/ctor_array.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ template <typename DataT, typename DimT, typename TestCaseT> class run_test {
131131
const DataT *const ref = shared_ref_data.data();
132132
DataT *const out = result.data();
133133

134-
cgh.single_task<ctors::Kernel<DataT, NumElems, TestCaseT>>(
134+
cgh.single_task<Kernel<DataT, NumElems, TestCaseT>>(
135135
[=]() SYCL_ESIMD_KERNEL {
136136
DataT ref_on_dev[NumElems];
137137
for (size_t i = 0; i < NumElems; ++i) {

SYCL/ESIMD/api/functional/ctors/ctor_copy.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ template <typename DataT, typename DimT, typename TestCaseT> class run_test {
127127
const DataT *const ref = shared_ref_data.data();
128128
DataT *const out = result.data();
129129

130-
cgh.single_task<ctors::Kernel<DataT, NumElems, TestCaseT>>(
130+
cgh.single_task<Kernel<DataT, NumElems, TestCaseT>>(
131131
[=]() SYCL_ESIMD_KERNEL {
132132
TestCaseT::template call_simd_ctor<DataT, NumElems>(ref, out);
133133
});

SYCL/ESIMD/api/functional/ctors/ctor_default.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ template <typename DataT, typename DimT, typename TestCaseT> struct run_test {
8787

8888
queue.submit([&](sycl::handler &cgh) {
8989
DataT *const out = result.data();
90-
cgh.single_task<ctors::Kernel<DataT, NumElems, TestCaseT>>(
90+
cgh.single_task<Kernel<DataT, NumElems, TestCaseT>>(
9191
[=]() SYCL_ESIMD_KERNEL {
9292
TestCaseT::template call_simd_ctor<DataT, NumElems>(out);
9393
});

SYCL/ESIMD/api/functional/ctors/ctor_fill.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ enum class init_val {
9898
ulp_half
9999
};
100100

101-
// Dummy kernel for submitting some code into device side.
101+
// Class used as a kernel ID.
102102
template <typename DataT, int NumElems, typename T, init_val BaseVal,
103103
init_val StepVal>
104104
struct kernel_for_fill;
@@ -173,16 +173,16 @@ template <init_val Val> std::string init_val_to_string() {
173173
template <typename DataT, int NumElems, typename ContextT, init_val BaseVal,
174174
init_val Step>
175175
class FillCtorTestDescription
176-
: public TestDescription<DataT, NumElems, ContextT> {
176+
: public ctors::TestDescription<DataT, NumElems, ContextT> {
177177
public:
178178
FillCtorTestDescription(size_t index, DataT retrieved_val, DataT expected_val,
179179
const std::string &data_type)
180-
: TestDescription<DataT, NumElems, ContextT>(index, retrieved_val,
181-
expected_val, data_type) {}
180+
: ctors::TestDescription<DataT, NumElems, ContextT>(
181+
index, retrieved_val, expected_val, data_type) {}
182182

183183
std::string to_string() const override {
184184
std::string log_msg(
185-
TestDescription<DataT, NumElems, ContextT>::to_string());
185+
ctors::TestDescription<DataT, NumElems, ContextT>::to_string());
186186

187187
log_msg += ", with base value: " + init_val_to_string<BaseVal>();
188188
log_msg += ", with step value: " + init_val_to_string<Step>();

SYCL/ESIMD/api/functional/ctors/ctor_move.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class const_ref {
8585
// instance
8686
template <typename DataT, typename DimT, typename TestCaseT> class run_test {
8787
static constexpr int NumElems = DimT::value;
88-
using KernelName = ctors::Kernel<DataT, NumElems, TestCaseT>;
88+
using KernelName = Kernel<DataT, NumElems, TestCaseT>;
8989

9090
public:
9191
bool operator()(sycl::queue &queue, const std::string &data_type) {

SYCL/ESIMD/api/functional/ctors/ctor_vector.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ template <typename DataT, typename DimT, typename TestCaseT> class run_test {
122122
const DataT *const ref = shared_ref_data.data();
123123
DataT *const out = result.data();
124124

125-
cgh.single_task<ctors::Kernel<DataT, NumElems, TestCaseT>>(
125+
cgh.single_task<Kernel<DataT, NumElems, TestCaseT>>(
126126
[=]() SYCL_ESIMD_KERNEL {
127127
TestCaseT::template call_simd_ctor<DataT, NumElems>(ref, out);
128128
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===-- common.hpp - Define common code for simd operators tests ----------===//
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+
///
9+
/// \file
10+
/// This file provides common things for simd operators tests.
11+
///
12+
//===----------------------------------------------------------------------===//
13+
14+
#pragma once
15+
16+
#include "../common.hpp"
17+
18+
namespace esimd_test::api::functional::operators {
19+
20+
template <typename DataT, int NumElems>
21+
class TestDescription : public ITestDescription {
22+
public:
23+
TestDescription(size_t index, DataT retrieved_val, DataT expected_val,
24+
const std::string &data_type)
25+
: m_data_type(data_type), m_retrieved_val(retrieved_val),
26+
m_expected_val(expected_val), m_index(index) {}
27+
28+
std::string to_string() const override {
29+
// TODO: Make strings for fp values more short during failure output, may be
30+
// by using hex representation
31+
std::string log_msg("Failed for simd<");
32+
33+
log_msg += m_data_type + ", " + std::to_string(NumElems) + ">";
34+
log_msg += ", retrieved: " + std::to_string(m_retrieved_val);
35+
log_msg += ", expected: " + std::to_string(m_expected_val);
36+
log_msg += ", at index: " + std::to_string(m_index);
37+
38+
return log_msg;
39+
}
40+
41+
private:
42+
const std::string m_data_type;
43+
const DataT m_retrieved_val;
44+
const DataT m_expected_val;
45+
const size_t m_index;
46+
};
47+
48+
} // namespace esimd_test::api::functional::operators
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===-- operator_assignment.hpp - Functions for tests on simd assignment
2+
// operators. --------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file
11+
/// This file provides functions for tests on simd assignment operators.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#pragma once
16+
17+
// The test proxy is used to verify the move assignment was called actually.
18+
#define __ESIMD_ENABLE_TEST_PROXY
19+
20+
#include "../shared_element.hpp"
21+
#include "common.hpp"
22+
23+
namespace esimd_test::api::functional::operators {
24+
25+
// The main test routine.
26+
// Using functor class to be able to iterate over the pre-defined data types.
27+
template <typename DataT, typename DimT, typename TestCaseT> class run_test {
28+
static constexpr int NumElems = DimT::value;
29+
30+
public:
31+
bool operator()(sycl::queue &queue, const std::string &data_type) {
32+
bool passed = true;
33+
const std::vector<DataT> ref_data = generate_ref_data<DataT, NumElems>();
34+
35+
// If current number of elements is equal to one, then run test with each
36+
// one value from reference data.
37+
// If current number of elements is greater than one, then run tests with
38+
// whole reference data.
39+
if constexpr (NumElems == 1) {
40+
for (size_t i = 0; i < ref_data.size(); ++i) {
41+
passed = run_verification(queue, {ref_data[i]}, data_type);
42+
}
43+
} else {
44+
passed = run_verification(queue, ref_data, data_type);
45+
}
46+
return passed;
47+
}
48+
49+
private:
50+
bool run_verification(sycl::queue &queue, const std::vector<DataT> &ref_data,
51+
const std::string &data_type) {
52+
assert(ref_data.size() == NumElems &&
53+
"Reference data size is not equal to the simd vector length.");
54+
55+
bool passed = true;
56+
57+
shared_allocator<DataT> allocator(queue);
58+
shared_vector<DataT> result(NumElems, allocator);
59+
shared_vector<DataT> shared_ref_data(ref_data.begin(), ref_data.end(),
60+
allocator);
61+
62+
shared_element<bool> is_correct_operator(queue, false);
63+
64+
queue.submit([&](sycl::handler &cgh) {
65+
const DataT *const ref = shared_ref_data.data();
66+
DataT *const out = result.data();
67+
const auto is_correct_operator_storage = is_correct_operator.data();
68+
69+
cgh.single_task<Kernel<DataT, NumElems, TestCaseT>>(
70+
[=]() SYCL_ESIMD_KERNEL {
71+
*is_correct_operator_storage =
72+
TestCaseT::template run<DataT, NumElems>(ref, out);
73+
});
74+
});
75+
queue.wait_and_throw();
76+
77+
for (size_t i = 0; i < result.size(); ++i) {
78+
if (!are_bitwise_equal(ref_data[i], result[i])) {
79+
passed = false;
80+
81+
const auto description = TestDescription<DataT, NumElems>(
82+
i, result[i], ref_data[i], data_type);
83+
log::fail(description);
84+
}
85+
}
86+
87+
if (!is_correct_operator.value()) {
88+
passed = false;
89+
log::note("Test failed due to " + TestCaseT::get_description() +
90+
" hasn't called for simd<" + data_type + ", " +
91+
std::to_string(NumElems) + ">.");
92+
}
93+
94+
return passed;
95+
}
96+
};
97+
98+
} // namespace esimd_test::api::functional::operators
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//==------- operator_assignment_move_and_copy_core.cpp - DPC++ ESIMD on-device
2+
// test -----------------------------------------------------------==//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
// REQUIRES: gpu, level_zero
10+
// XREQUIRES: gpu
11+
// TODO gpu and level_zero in REQUIRES due to only this platforms supported yet.
12+
// The current "REQUIRES" should be replaced with "gpu" only as mentioned in
13+
// "XREQUIRES".
14+
// RUN: %clangxx -fsycl %s -fsycl-device-code-split=per_kernel -o %t.out
15+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
16+
// XFAIL: *
17+
// TODO Remove XFAIL once the simd vector provides move assignment operator
18+
//
19+
// Test for simd move and copy assignment operators.
20+
// The test creates source simd instance with reference data and invokes move or
21+
// copy assignment operator from source to destination simd instance. It is
22+
// expected for destination simd instance to store a bitwise same data as the
23+
// reference one.
24+
25+
#include "operator_assignment.hpp"
26+
27+
using namespace sycl::ext::intel::experimental::esimd;
28+
using namespace esimd_test::api::functional;
29+
30+
// Descriptor class for the case of calling move assignment operator.
31+
struct move_assignment {
32+
static std::string get_description() { return "move assignment operator"; }
33+
34+
template <typename DataT, int NumElems>
35+
static bool run(const DataT *const ref_data, DataT *const out) {
36+
simd<DataT, NumElems> source_simd;
37+
source_simd.copy_from(ref_data);
38+
simd<DataT, NumElems> simd_obj;
39+
simd_obj = std::move(source_simd);
40+
simd_obj.copy_to(out);
41+
return simd_obj.get_test_proxy().was_move_destination() == true;
42+
}
43+
};
44+
45+
// Descriptor class for the case of calling copy assignment operator.
46+
struct copy_assignment {
47+
static std::string get_description() { return "copy assignment operator"; }
48+
49+
template <typename DataT, int NumElems>
50+
static bool run(const DataT *const ref_data, DataT *const out) {
51+
simd<DataT, NumElems> source_simd;
52+
source_simd.copy_from(ref_data);
53+
simd<DataT, NumElems> simd_obj;
54+
simd_obj = source_simd;
55+
simd_obj.copy_to(out);
56+
return simd_obj.get_test_proxy().was_move_destination() == false;
57+
}
58+
};
59+
60+
int main(int, char **) {
61+
sycl::queue queue(esimd_test::ESIMDSelector{},
62+
esimd_test::createExceptionHandler());
63+
64+
bool passed = true;
65+
66+
const auto types = get_tested_types<tested_types::all>();
67+
const auto dims = get_all_dimensions();
68+
69+
const auto context =
70+
unnamed_type_pack<move_assignment, copy_assignment>::generate();
71+
72+
passed &=
73+
for_all_combinations<operators::run_test>(types, dims, context, queue);
74+
75+
std::cout << (passed ? "=== Test passed\n" : "=== Test FAILED\n");
76+
return passed ? 0 : 1;
77+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===-- shared_elements.hpp - Function that provides USM with a smart pointer.
2+
// -------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file
11+
/// This file provides data struct that lets interact with USM with a smart
12+
/// pointer that lets avoid memory leaks.
13+
///
14+
//===----------------------------------------------------------------------===//
15+
16+
#pragma once
17+
18+
#include <sycl/sycl.hpp>
19+
20+
#include <functional>
21+
#include <memory>
22+
23+
namespace esimd_test::api::functional {
24+
25+
// Provides APIs to interact with USM pointer without memory leaks for a single
26+
// variable. Might be useful to provide access to a single boolean flag to store
27+
// success, for example.
28+
template <typename T> class shared_element {
29+
std::unique_ptr<T, std::function<void(T *)>> m_allocated_data;
30+
31+
public:
32+
shared_element(sycl::queue &queue, T initial_value) {
33+
const auto &device{queue.get_device()};
34+
const auto &context{queue.get_context()};
35+
36+
auto deleter = [=](T *ptr) { sycl::free(ptr, context); };
37+
38+
m_allocated_data = std::unique_ptr<T, decltype(deleter)>(
39+
sycl::malloc_shared<T>(1, device, context), deleter);
40+
41+
assert(m_allocated_data && "USM memory allocation failed");
42+
*m_allocated_data = initial_value;
43+
}
44+
45+
T *data() { return m_allocated_data.get(); }
46+
47+
const T *data() const { return m_allocated_data.get(); }
48+
49+
T value() { return *m_allocated_data.get(); }
50+
51+
T value() const { return *m_allocated_data.get(); }
52+
};
53+
54+
} // namespace esimd_test::api::functional

0 commit comments

Comments
 (0)