Skip to content

Commit bcf0f44

Browse files
sommerlukasadamfidel
authored andcommitted
[SYCL][RTC] Implement specified error behavior (intel#17331)
Detect error scenarios in `sycl::ext::oneapi::build` and throw the errors specified in the extension. This handles two scenarios: - Calling build where one of the devices given in the list does not support the source language of the bundle. - Calling build where one of the devices given in the list does not belong to the context of the source bundle. --------- Signed-off-by: Lukas Sommer <[email protected]>
1 parent ef50d1e commit bcf0f44

File tree

4 files changed

+102
-3
lines changed

4 files changed

+102
-3
lines changed

sycl/source/detail/kernel_bundle_impl.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,21 @@ class kernel_bundle_impl {
495495
std::vector<ur_device_handle_t> DeviceVec;
496496
DeviceVec.reserve(Devices.size());
497497
for (const auto &SyclDev : Devices) {
498-
ur_device_handle_t Dev = getSyclObjImpl(SyclDev)->getHandleRef();
498+
DeviceImplPtr DevImpl = getSyclObjImpl(SyclDev);
499+
if (!ContextImpl->hasDevice(DevImpl)) {
500+
throw sycl::exception(make_error_code(errc::invalid),
501+
"device not part of kernel_bundle context");
502+
}
503+
if (!DevImpl->extOneapiCanCompile(MLanguage)) {
504+
// This error cannot not be exercised in the current implementation, as
505+
// compatibility with a source language depends on the backend's
506+
// capabilities and all devices in one context share the same backend in
507+
// the current implementation, so this would lead to an error already
508+
// during construction of the source bundle.
509+
throw sycl::exception(make_error_code(errc::invalid),
510+
"device does not support source language");
511+
}
512+
ur_device_handle_t Dev = DevImpl->getHandleRef();
499513
DeviceVec.push_back(Dev);
500514
}
501515

sycl/test-e2e/KernelCompiler/kernel_compiler_basic.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//==- kernel_compiler_sycl_jit.cpp --- kernel_compiler extension tests -----==//
1+
//==---- kernel_compiler_basic.cpp --- kernel_compiler extension tests -----==//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//==- kernel_compiler_context_error.cpp -- kernel_compiler extension 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+
// REQUIRES: (opencl || level_zero)
10+
11+
// UNSUPPORTED: accelerator
12+
// UNSUPPORTED-INTENDED: while accelerator is AoT only, this cannot run there.
13+
14+
// RUN: %{build} -o %t.out
15+
// RUN: %{run-unfiltered-devices} %t.out
16+
17+
#include <sycl/detail/core.hpp>
18+
#include <sycl/kernel_bundle.hpp>
19+
#include <sycl/usm.hpp>
20+
21+
namespace syclexp = sycl::ext::oneapi::experimental;
22+
23+
const std::string source = R"""(
24+
#include <sycl/sycl.hpp>
25+
namespace syclext = sycl::ext::oneapi;
26+
namespace syclexp = sycl::ext::oneapi::experimental;
27+
28+
extern "C"
29+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY((syclexp::nd_range_kernel<1>))
30+
void iota(float start, float *ptr) {
31+
size_t id = syclext::this_work_item::get_nd_item<1>().get_global_linear_id();
32+
ptr[id] = start + static_cast<float>(id);
33+
}
34+
)""";
35+
36+
int main() {
37+
38+
auto has_multiple_compatible_devices = [](sycl::platform platform) -> bool {
39+
auto devices = platform.get_devices();
40+
if (devices.size() < 2) {
41+
return false;
42+
}
43+
for (auto dev : devices) {
44+
if (!dev.ext_oneapi_can_compile(syclexp::source_language::sycl)) {
45+
return false;
46+
}
47+
}
48+
return true;
49+
};
50+
51+
std::vector<sycl::device> all_devices = [&]() -> std::vector<sycl::device> {
52+
for (auto platform : sycl::platform::get_platforms()) {
53+
if (has_multiple_compatible_devices(platform)) {
54+
return platform.get_devices();
55+
}
56+
}
57+
return {};
58+
}();
59+
60+
if (all_devices.size() < 2) {
61+
std::cerr << "Cannot find platform with more than 1 device, skipping"
62+
<< std::endl;
63+
return 0;
64+
}
65+
66+
sycl::context single_device_context{all_devices.front()};
67+
68+
// Create a source kernel bundle with a context that contains only one device.
69+
sycl::kernel_bundle<sycl::bundle_state::ext_oneapi_source> kb_src =
70+
syclexp::create_kernel_bundle_from_source(
71+
single_device_context, syclexp::source_language::sycl, source);
72+
73+
// Compile the kernel. There is no need to use the "registered_names"
74+
// property because the kernel is declared extern "C".
75+
try {
76+
syclexp::build(kb_src, all_devices);
77+
assert(false && "out-of-context device not detected");
78+
} catch (sycl::exception &e) {
79+
assert(e.code() == sycl::errc::invalid);
80+
assert(std::string(e.what()).find(
81+
"device not part of kernel_bundle context") !=
82+
std::string::npos);
83+
}
84+
return 0;
85+
}

sycl/test/e2e_test_requirements/no_sycl_hpp_in_e2e_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// CHECK-DAG: README.md
77
// CHECK-DAG: lit.cfg.py
88
//
9-
// CHECK-NUM-MATCHES: 10
9+
// CHECK-NUM-MATCHES: 11
1010
//
1111
// This test verifies that `<sycl/sycl.hpp>` isn't used in E2E tests. Instead,
1212
// fine-grained includes should used, see

0 commit comments

Comments
 (0)