Skip to content

Commit

Permalink
Test marray on device
Browse files Browse the repository at this point in the history
This commit makes marray tests run checks on both device and host, where
they would only run on host previously.

Signed-off-by: Larsen, Steffen <[email protected]>
  • Loading branch information
steffenlarsen committed Jan 10, 2024
1 parent 6052dc6 commit 65d028f
Show file tree
Hide file tree
Showing 25 changed files with 1,432 additions and 155 deletions.
5 changes: 5 additions & 0 deletions tests/marray/marray_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ constexpr sycl::marray<DataT, NumElements> iota_marray() {
std::make_index_sequence<NumElements>());
}

template <class ForwardIt, class T>
void iota(ForwardIt first, ForwardIt last, T value) {
for (; first != last; ++first) *first = value++;
}

} // namespace marray_common

#endif // SYCL_CTS_TEST_MARRAY_MARRAY_COMMON_H
124 changes: 84 additions & 40 deletions tests/marray/marray_constructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,81 +31,125 @@ template <typename DataT, typename NumElementsT>
class run_marray_constructor_test {
static constexpr std::size_t NumElements = NumElementsT::value;

using marray_t = sycl::marray<DataT, NumElements>;
static constexpr size_t num_test_cases = 7;

private:
template <size_t num_elements = NumElements,
std::enable_if_t<num_elements == 1, bool> = true>
void check_constexpr_single_element() {}
static constexpr const char* check_names[num_test_cases] = {
"default constructor",
"scalar constructor",
"variadic constructor (NumElements DataT instances)",
"variadic constructor (one DataT instance, one marray instance)",
"variadic constructor (one marray instance, one DataT instance)",
"copy constructor",
"copy constructor rval reference"};

template <size_t num_elements = NumElements,
std::enable_if_t<num_elements != 1, bool> = true>
void check_constexpr_single_element() {
// one DataT instance, one marray instance
{
constexpr sycl::marray<DataT, num_elements - 1> ma_const =
marray_common::iota_marray<DataT, num_elements - 1, 2>();
constexpr marray_t ma{1, ma_const};
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
CHECK(value_operations::are_equal(ma_inc, ma));
}

// one marray instance, one DataT instance
{
constexpr sycl::marray<DataT, num_elements - 1> ma_const =
marray_common::iota_marray<DataT, num_elements - 1, 1>();
constexpr marray_t ma{ma_const, DataT(num_elements)};
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
CHECK(value_operations::are_equal(ma_inc, ma));
}
}

public:
void operator()(const std::string&) {
INFO("for number of elements \"" << NumElements << "\": ");
using marray_t = sycl::marray<DataT, NumElements>;

template <typename IteratorT>
static void run_checks(IteratorT results) {
// default constructor
{
marray_t ma;
CHECK(value_operations::are_equal(ma, DataT{}));
*(results++) = value_operations::are_equal(ma, DataT{});
}

// scalar constructor
{
constexpr DataT value{1};
constexpr marray_t ma{value};
CHECK(value_operations::are_equal(ma, value));
*(results++) = value_operations::are_equal(ma, value);
}

// variadic constructor
{
// NumElements DataT instances
constexpr auto a = marray_common::iota_marray<DataT, NumElements, 1>();
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
CHECK(value_operations::are_equal(ma_inc, a));
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
*(results++) = value_operations::are_equal(ma_inc, a);

// only compiled when NumElements != 1
check_constexpr_single_element();
if constexpr (NumElements != 1) {
// one DataT instance, one marray instance
{
constexpr sycl::marray<DataT, NumElements - 1> ma_const =
marray_common::iota_marray<DataT, NumElements - 1, 2>();
constexpr marray_t ma{1, ma_const};
marray_t ma_inc;
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
*(results++) = value_operations::are_equal(ma_inc, ma);
}

// one marray instance, one DataT instance
{
constexpr sycl::marray<DataT, NumElements - 1> ma_const =
marray_common::iota_marray<DataT, NumElements - 1, 1>();
constexpr marray_t ma{ma_const, DataT(NumElements)};
marray_t ma_inc;
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
*(results++) = value_operations::are_equal(ma_inc, ma);
}
} else {
// Two checks were skipped.
*(results++) = true;
*(results++) = true;
}
}

// copy constructor
{
constexpr DataT value{1};
constexpr marray_t rhs{value};
constexpr marray_t ma{rhs};
CHECK(value_operations::are_equal(ma, value));
*(results++) = value_operations::are_equal(ma, value);
}

// copy constructor rval reference
{
constexpr marray_t ma{
marray_common::iota_marray<DataT, NumElements, 1>()};
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
CHECK(value_operations::are_equal(ma_inc, ma));
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
*(results++) = value_operations::are_equal(ma_inc, ma);
}
}

public:
void operator()(const std::string&) {
INFO("for number of elements \"" << NumElements << "\": ");

{
INFO("validation on host");

bool check_results[num_test_cases] = {false};
run_checks(check_results);
for (size_t i = 0; i < num_test_cases; ++i) {
INFO(check_names[i]);
CHECK(check_results[i]);
}
}

{
INFO("validation on device");

auto queue = sycl_cts::util::get_cts_object::queue();
bool check_results[num_test_cases] = {false};
{
sycl::buffer<bool, 1> check_results_buff{
check_results, sycl::range<1>{num_test_cases}};

queue
.submit([&](sycl::handler& cgh) {
sycl::accessor check_results_acc{check_results_buff, cgh,
sycl::read_write};
cgh.single_task([=]() { run_checks(check_results_acc.begin()); });
})
.wait_and_throw();
}
run_checks(check_results);
for (size_t i = 0; i < num_test_cases; ++i) {
INFO(check_names[i]);
CHECK(check_results[i]);
}
}
}
};
Expand Down
150 changes: 105 additions & 45 deletions tests/marray/marray_members.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,116 +32,176 @@ template <typename DataT, typename NumElementsT>
class run_marray_members_test {
static constexpr std::size_t NumElements = NumElementsT::value;

using marray_t = sycl::marray<DataT, NumElements>;

private:
template <size_t num_elements,
std::enable_if_t<num_elements != 1, bool> = true>
void check_conversion() {}

template <size_t num_elements,
std::enable_if_t<num_elements == 1, bool> = true>
void check_conversion() {
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
DataT t{ma_inc};
CHECK((t == DataT{1}));
}
static constexpr size_t num_test_cases = 19;

static constexpr const char* check_names[num_test_cases] = {
"implicit conversion",
"size() (noexcept)",
"size() (result)",
"operator[] (before write)",
"operator[] (after write)",
"const operator[]",
"operator=(marray)",
"operator=(T)",
"iterator (increment)",
"iterator (decrement)",
"iterator (equivalence)",
"const iterator (increment)",
"const iterator (decrement)",
"const iterator (equivalence)",
"value_type",
"reference",
"const_reference",
"iterator",
"const_iterator",
};

public:
void operator()(const std::string&) {
INFO("for number of elements \"" << NumElements << "\": ");
using marray_t = sycl::marray<DataT, NumElements>;

template <typename IteratorT>
static void run_checks(IteratorT results) {
// implicit conversion
{
// only compiled when NumElements == 1
check_conversion<NumElements>();
if constexpr (NumElements == 1) {
marray_t ma_inc;
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
DataT t{ma_inc};
*(results++) = (t == DataT{1});
} else {
// One check were skipped.
*(results++) = true;
}
}

// size()
{
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
CHECK(noexcept(ma_inc.size()));
CHECK((ma_inc.size() == NumElements));
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
*(results++) = noexcept(ma_inc.size());
*(results++) = (ma_inc.size() == NumElements);
}

// operator[]
{
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
CHECK((ma_inc[0] == DataT{1}));
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
*(results++) = (ma_inc[0] == DataT{1});
ma_inc[0] = DataT{0};
CHECK((ma_inc[0] == DataT{0}));
*(results++) = (ma_inc[0] == DataT{0});
}

// const operator[]
{
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
const marray_t ma_const{ma_inc};
CHECK((ma_const[0] == DataT{1}));
*(results++) = (ma_const[0] == DataT{1});
}

// operator=(marray)
{
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
const marray_t ma_const{ma_inc};

marray_t ma_tmp{DataT{0}};
ma_tmp = ma_const;
CHECK(value_operations::are_equal(ma_tmp, ma_const));
*(results++) = value_operations::are_equal(ma_tmp, ma_const);
}

// operator=(T)
{
marray_t ma_tmp{DataT{0}};
ma_tmp = DataT{1};
CHECK(value_operations::are_equal(ma_tmp, marray_t(DataT(1))));
*(results++) = value_operations::are_equal(ma_tmp, marray_t(DataT(1)));
}

// iterator
{
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);

auto it_ma = ma_inc.begin();
auto it_ma_tmp = it_ma;
it_ma++;
if (NumElements > 1) {
CHECK((*it_ma == DataT(2)));
*(results++) = (*it_ma == DataT(2));
} else {
*(results++) = true;
}
it_ma--;
CHECK((*it_ma == DataT(1)));
CHECK((it_ma == it_ma_tmp));
*(results++) = (*it_ma == DataT(1));
*(results++) = (it_ma == it_ma_tmp);
}

// const iterator
{
marray_t ma_inc;
std::iota(ma_inc.begin(), ma_inc.end(), 1);
marray_common::iota(ma_inc.begin(), ma_inc.end(), 1);
const marray_t ma_const = ma_inc;
auto it_ma = ma_const.begin();
auto it_ma_tmp = it_ma;
it_ma++;
if (NumElements > 1) {
CHECK((*it_ma == DataT(2)));
*(results++) = (*it_ma == DataT(2));
} else {
*(results++) = true;
}
it_ma--;
CHECK((*it_ma == DataT(1)));
CHECK((it_ma == it_ma_tmp));
*(results++) = (*it_ma == DataT(1));
*(results++) = (it_ma == it_ma_tmp);
}

// member types
{
STATIC_CHECK(std::is_same_v<typename marray_t::value_type, DataT>);
STATIC_CHECK(std::is_same_v<typename marray_t::reference, DataT&>);
STATIC_CHECK(
std::is_same_v<typename marray_t::const_reference, const DataT&>);
STATIC_CHECK(std::is_same_v<typename marray_t::iterator, DataT*>);
STATIC_CHECK(
std::is_same_v<typename marray_t::const_iterator, const DataT*>);
*(results++) = std::is_same_v<typename marray_t::value_type, DataT>;
*(results++) = std::is_same_v<typename marray_t::reference, DataT&>;
*(results++) =
std::is_same_v<typename marray_t::const_reference, const DataT&>;
*(results++) = std::is_same_v<typename marray_t::iterator, DataT*>;
*(results++) =
std::is_same_v<typename marray_t::const_iterator, const DataT*>;
}
}

public:
void operator()(const std::string&) {
INFO("for number of elements \"" << NumElements << "\": ");

{
INFO("validation on host");

bool check_results[num_test_cases] = {false};
run_checks(check_results);
for (size_t i = 0; i < num_test_cases; ++i) {
INFO(check_names[i]);
CHECK(check_results[i]);
}
}

{
INFO("validation on device");

auto queue = sycl_cts::util::get_cts_object::queue();
bool check_results[num_test_cases] = {false};
{
sycl::buffer<bool, 1> check_results_buff{
check_results, sycl::range<1>{num_test_cases}};

queue
.submit([&](sycl::handler& cgh) {
sycl::accessor check_results_acc{check_results_buff, cgh,
sycl::read_write};
cgh.single_task([=]() { run_checks(check_results_acc.begin()); });
})
.wait_and_throw();
}
run_checks(check_results);
for (size_t i = 0; i < num_test_cases; ++i) {
INFO(check_names[i]);
CHECK(check_results[i]);
}
}
}
};
Expand Down
Loading

0 comments on commit 65d028f

Please sign in to comment.