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

[SYCL] updating tests for SYCL2020 errc conformance #857

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions SYCL/Basic/accessor/accessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,5 +657,53 @@ int main() {
return 1;
}
}

// exceptions with illegal ranges or no_init
{
const size_t bufSize = 10;
std::vector<int> res(bufSize);
sycl::range<1> r(bufSize);
sycl::buffer<int, 1> b(res.data(), r);
sycl::range<1> illegalR(bufSize + 1);
sycl::id<1> offset(bufSize);

// illegal ranges
try {
auto acc = b.get_access<sycl::access::mode::read_write>(illegalR, offset);
assert(false && "operation should not have succeeded");
} catch (sycl::exception &e) {
assert(e.code() == sycl::errc::invalid && "errc should be errc::invalid");
}
try {
sycl::queue q;
q.submit([&](sycl::handler &cgh) {
auto acc = b.get_access<sycl::access::mode::read_write>(cgh, illegalR);
});
q.wait_and_throw();
assert(false &&
"we should not be here. operation should not have succeeded");
} catch (sycl::exception &e) {
assert(e.code() == sycl::errc::invalid && "errc should be errc::invalid");
}

// no_init incompatible with read_only
try {
sycl::host_accessor out{b, sycl::read_only, sycl::no_init};
assert(false && "operation should have failed");
} catch (sycl::exception &e) {
assert(e.code() == sycl::errc::invalid && "errc should be errc::invalid");
}
try {
sycl::queue q;
q.submit([&](sycl::handler &cgh) {
sycl::accessor out{b, cgh, sycl::read_only, sycl::no_init};
});
q.wait_and_throw();
assert(false && "we should not be here. operation should have failed");
} catch (sycl::exception &e) {
assert(e.code() == sycl::errc::invalid && "errc should be errc::invalid");
}
}

std::cout << "Test passed" << std::endl;
}
2 changes: 1 addition & 1 deletion SYCL/Basic/buffer/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ int main() {
myQueue.submit([&](handler &cgh) {
accessor<int, 2, access::mode::write, access::target::device,
access::placeholder::false_t>
B(Buffer, cgh, range<2>(20, 20), id<2>(10, 10));
B(Buffer, cgh, range<2>(10, 10), id<2>(10, 10));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look unrelated to SYCL2020 errc conformance. Can we remove them from this PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the conformance checks is that out-of-bounds range args should trigger an exception in accessor construction. I added that. Without this change, this test triggers that error.

cgh.parallel_for<class bufferByRangeOffset>(
range<2>{10, 5}, [=](id<2> index) { B[index] = 1; });
});
Expand Down
27 changes: 27 additions & 0 deletions SYCL/Basic/buffer/buffer_full_copy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,39 @@ void check_copy_host_to_device(cl::sycl::queue &Queue) {
}
}

void check_exception_code() {
sycl::queue q;

const size_t bufSize = 10;
std::vector<int> res(bufSize);
// std::iota(res.begin(), res.end(), 1);
sycl::range<1> r(bufSize);
sycl::buffer<int, 1> b(res.data(), r);
sycl::range<1> smallRange(bufSize / 2);
sycl::id<1> offset(bufSize);

try {
q.submit([&](sycl::handler &cgh) {
sycl::accessor src(b, cgh);
sycl::accessor destToSmall(b, cgh, smallRange);
cgh.copy(src, destToSmall);
});
q.wait_and_throw();

assert(false &&
"copy with too small Dest arg should have thrown an exception");
} catch (sycl::exception e) {
assert(e.code() == sycl::errc::invalid);
}
}

int main() {
try {
cl::sycl::queue Queue;
check_copy_host_to_device(Queue);
check_copy_device_to_host(Queue);
check_fill(Queue);
check_exception_code();
} catch (cl::sycl::exception &ex) {
std::cerr << ex.what() << std::endl;
return 1;
Expand Down
48 changes: 40 additions & 8 deletions SYCL/Basic/buffer/subbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
// RUN: %CPU_RUN_PLACEHOLDER %t.out
// RUN: %GPU_RUN_PLACEHOLDER %t.out
// RUN: %ACC_RUN_PLACEHOLDER %t.out

// UNSUPPORTED: (opencl && gpu)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All changes in this file doesn't look related to SYCL2020 errc conformance, I couldn't find any errc checks in the file.
It is possible to move them to a separate PR if they are unrelated? Does it make sense to create a separate test for your modified test case (which shows a problem on opencl gpu) to avoid disabling whole test for opencl gpu?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was using an out-of-bounds range argument to an accessor. And, oddly, that was masking an error that is occurring over on OCL:GPU. I reduced that down and reported it, there is a ticket against it now. But in the interim, this test won't pass on OCL:GPU, not due to any bug in the error system, but due to a real bug that OCL:GPU has handling offsets. Strangely, that is the only device with the problem. L0, OCL:CPU, OCL:ACC and Host are all fine.


//
//==---------- subbuffer.cpp --- sub-buffer basic test ---------------------==//
//
Expand Down Expand Up @@ -71,26 +74,34 @@ void check1DSubBuffer(cl::sycl::queue &q) {
size *= 2;

std::size_t offset = size / 2, subbuf_size = 10, offset_inside_subbuf = 3,
subbuffer_access_range = 10;
subbuffer_access_range = subbuf_size - offset_inside_subbuf; // 7.
std::vector<int> vec(size);
std::vector<int> vec2(subbuf_size, 0);
std::iota(vec.begin(), vec.end(), 0);

std::cout << "buffer size: " << size << ", subbuffer start: " << offset
<< std::endl;

try {
cl::sycl::buffer<int, 1> buf(vec.data(), size);
cl::sycl::buffer<int, 1> buf2(vec2.data(), subbuf_size);
// subbuffer is 10 elements, starting at midpoint. (typically 32)
cl::sycl::buffer<int, 1> subbuf(buf, cl::sycl::id<1>(offset),
cl::sycl::range<1>(subbuf_size));

// test offset accessor against a subbuffer
q.submit([&](cl::sycl::handler &cgh) {
// accessor starts at the third element of the subbuffer
// and can read for 7 more (ie to the end of the subbuffer)
auto acc = subbuf.get_access<cl::sycl::access::mode::read_write>(
cgh, cl::sycl::range<1>(subbuffer_access_range),
cl::sycl::id<1>(offset_inside_subbuf));
cgh.parallel_for<class foobar>(
cl::sycl::range<1>(subbuffer_access_range - offset_inside_subbuf),
[=](cl::sycl::id<1> i) { acc[i] *= -1; });
// subrange is made negative. ( 32 33 34 -35 -36 -37 -38 -39 -40 -41)
cgh.parallel_for<class foobar>(cl::sycl::range<1>(subbuffer_access_range),
[=](cl::sycl::id<1> i) { acc[i] *= -1; });
});

// copy results of last operation back to buf2/vec2
q.submit([&](cl::sycl::handler &cgh) {
auto acc_sub = subbuf.get_access<cl::sycl::access::mode::read>(cgh);
auto acc_buf = buf2.get_access<cl::sycl::access::mode::write>(cgh);
Expand All @@ -99,27 +110,48 @@ void check1DSubBuffer(cl::sycl::queue &q) {
[=](cl::sycl::id<1> i) { acc_buf[i] = acc_sub[i]; });
});

// multiple entire subbuffer by 10.
// now original buffer will be
// (..29 30 31 | 320 330 340 -350 -360 -370 -380 -390 -400 -410 | 42 43 44
// ...)
q.submit([&](cl::sycl::handler &cgh) {
auto acc_sub = subbuf.get_access<cl::sycl::access::mode::read_write>(
cgh, cl::sycl::range<1>(subbuffer_access_range));
cgh, cl::sycl::range<1>(subbuf_size));
cgh.parallel_for<class foobar_1>(
cl::sycl::range<1>(subbuffer_access_range),
cl::sycl::range<1>(subbuf_size),
[=](cl::sycl::id<1> i) { acc_sub[i] *= 10; });
});
q.wait_and_throw();

// buffers go out of scope. data must be copied back to vector no later than
// this.
} catch (const cl::sycl::exception &e) {
std::cerr << e.what() << std::endl;
assert(false && "Exception was caught");
}

// check buffer data in the area of the subbuffer
// OCL:GPU confused => 320 330 340 -350 -360 -370 -380 39 40 41
// every other device => 320 330 340 -350 -360 -370 -380 -390 -400 -410
for (int i = offset; i < offset + subbuf_size; ++i)
assert(vec[i] == (i < offset + offset_inside_subbuf ? i * 10 : i * -10) &&
"Invalid result in 1d sub buffer");
"Invalid result in buffer overlapped by 1d sub buffer");

// check buffer data in the area OUTSIDE the subbuffer
for (int i = 0; i < size; i++) {
if (i < offset)
assert(vec[i] == i && "data preceding subbuffer incorrectly altered");

if (i > offset + subbuf_size)
assert(vec[i] == i && "data following subbuffer incorrectly altered");
}

// check the copy of the subbuffer data after the first operation
// OCL:GPU => 32 33 34 -35 -36 -37 -38 0 0 0
// everyone else => 32 33 34 -35 -36 -37 -38 -39 -40 -41
for (int i = 0; i < subbuf_size; ++i)
assert(vec2[i] == (i < 3 ? (offset + i) : (offset + i) * -1) &&
"Invalid result in 1d sub buffer");
"Invalid result in captured 1d sub buffer, vec2");
}

void checkExceptions() {
Expand Down
9 changes: 9 additions & 0 deletions SYCL/Basic/interop/get_native_ze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,14 @@ int main() {
ze_result_t Err = zeKernelGetProperties(Handle, &KernelProperties);
assert(Err == ZE_RESULT_SUCCESS);

// SYCL2020 4.5.1.2 - verify exception errc
try {
// this test is L0 only, so we ask for an unavailable backend.
auto BE2 = sycl::get_native<sycl::backend::opencl>(Q);
assert(false && "we should not be here.");
} catch (sycl::exception e) {
assert(e.code() == sycl::errc::backend_mismatch && "wrong error code");
}

return 0;
}
24 changes: 24 additions & 0 deletions SYCL/Basic/partition_supported.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,24 @@ int main() {
return -1;
}
}
auto maxUnits = dev.get_info<sycl::info::device::max_compute_units>();
try {
std::vector<sycl::device> v = dev.create_sub_devices<
sycl::info::partition_property::partition_equally>(maxUnits + 1);
std::cerr << "create_sub_devices with more than max_compute_units should "
"have thrown an error"
<< std::endl;
return -1;
} catch (sycl::exception &ex) {
if (ex.code() != sycl::errc::invalid) {
std::cerr << "while an exception was correctly thrown, it has the "
"wrong error code"
"we should have received"
<< sycl::errc::invalid << "but instead got"
<< ex.code().value() << std::endl;
return -1;
}
}
} else {
try {
auto subDevices = dev.create_sub_devices<
Expand All @@ -85,6 +103,12 @@ int main() {
<< std::endl;
return -1;
} catch (const cl::sycl::feature_not_supported &e) {
if (e.code() != sycl::errc::feature_not_supported) {
std::cerr
<< "error code should be errc::feature_not_supported instead of "
<< e.code().value() << std::endl;
return -1;
}
} catch (...) {
std::cerr << "device::create_sub_device(info::partition_affinity_domain) "
"should have thrown cl::sycl::feature_not_supported"
Expand Down
8 changes: 5 additions & 3 deletions SYCL/Basic/queue/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,11 @@ int main() {
context Context(deviceA);
queue Queue(Context, deviceB);
assert(Context == Queue.get_context());
} catch (std::exception &e) {
std::cout << "Exception check passed: " << e.what() << std::endl;
GotException = true;
} catch (sycl::exception &e) {
if (e.code() == sycl::errc::invalid) {
std::cout << "Exception check passed: " << e.what() << std::endl;
GotException = true;
}
}
assert(GotException);
}
Expand Down