Skip to content

Commit e95c184

Browse files
[SYCL] Enforces exception on empty device vector in sycl::link (#4760)
The SYCL 2020 specification states that sycl::link must fail with a SYCL exception with errc::invalid if the vector of devices is empty. However the implementation of sycl::link skips this check if the list of kernel bundle objects is empty as well. These changes move the aforementioned check for devices earlier in the implementation of sycl::link and throws an exception even if there are no kernel bundle objects specified. Signed-off-by: Steffen Larsen <steffen.larsen@intel.com>
1 parent a8bb540 commit e95c184

File tree

2 files changed

+70
-5
lines changed

2 files changed

+70
-5
lines changed

sycl/source/detail/kernel_bundle_impl.hpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ class kernel_bundle_impl {
158158
std::vector<device> Devs, const property_list &PropList)
159159
: MDevices(std::move(Devs)) {
160160

161+
if (MDevices.empty())
162+
throw sycl::exception(make_error_code(errc::invalid),
163+
"Vector of devices is empty");
164+
161165
if (ObjectBundles.empty())
162166
return;
163167

@@ -184,11 +188,10 @@ class kernel_bundle_impl {
184188
Dev);
185189
});
186190
});
187-
if (MDevices.empty() || !AllDevsAssociatedWithInputBundles)
188-
throw sycl::exception(
189-
make_error_code(errc::invalid),
190-
"Not all devices are in the set of associated "
191-
"devices for input bundles or vector of devices is empty");
191+
if (!AllDevsAssociatedWithInputBundles)
192+
throw sycl::exception(make_error_code(errc::invalid),
193+
"Not all devices are in the set of associated "
194+
"devices for input bundles");
192195

193196
// TODO: Unify with c'tor for sycl::comile and sycl::build by calling
194197
// sycl::join on vector of kernel_bundles

sycl/unittests/SYCL2020/KernelBundle.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,65 @@ TEST(KernelBundle, UseKernelBundleWrongContextPrimaryQueueAndSecondaryQueue) {
564564
FAIL() << "Unexpected exception was thrown in submit.";
565565
}
566566
}
567+
568+
TEST(KernelBundle, EmptyDevicesKernelBundleLinkException) {
569+
sycl::platform Plt{sycl::default_selector()};
570+
if (Plt.is_host()) {
571+
std::cerr << "Test is not supported on host, skipping\n";
572+
return;
573+
}
574+
575+
if (Plt.get_backend() == sycl::backend::cuda) {
576+
std::cerr << "Test is not supported on CUDA platform, skipping\n";
577+
return;
578+
}
579+
580+
if (Plt.get_backend() == sycl::backend::hip) {
581+
std::cout << "Test is not supported on HIP platform, skipping\n";
582+
return;
583+
}
584+
585+
sycl::unittest::PiMock Mock{Plt};
586+
setupDefaultMockAPIs(Mock);
587+
588+
const sycl::device Dev = Plt.get_devices()[0];
589+
sycl::queue Queue{Dev};
590+
const sycl::context Ctx = Queue.get_context();
591+
592+
auto EmptyKernelBundle =
593+
sycl::get_kernel_bundle<sycl::bundle_state::object>(Ctx, {Dev}, {});
594+
595+
std::vector<sycl::device> EmptyDevices{};
596+
597+
// Case without an object bundle.
598+
try {
599+
auto LinkBundle = sycl::link(EmptyKernelBundle, EmptyDevices);
600+
FAIL() << "No exception was thrown.";
601+
} catch (const sycl::exception &e) {
602+
ASSERT_EQ(e.code().value(), static_cast<int>(sycl::errc::invalid))
603+
<< "sycl::exception code was not the expected "
604+
"sycl::errc::invalid.";
605+
// Expected path
606+
} catch (...) {
607+
FAIL() << "Unexpected exception was thrown in sycl::link.";
608+
}
609+
610+
sycl::kernel_bundle KernelBundle =
611+
sycl::get_kernel_bundle<TestKernel, sycl::bundle_state::input>(Ctx,
612+
{Dev});
613+
614+
auto ObjBundle = sycl::compile(KernelBundle, KernelBundle.get_devices());
615+
EXPECT_FALSE(ObjBundle.empty()) << "Expect non-empty obj kernel bundle";
616+
617+
try {
618+
auto LinkBundle = sycl::link(ObjBundle, EmptyDevices);
619+
FAIL() << "No exception was thrown.";
620+
} catch (const sycl::exception &e) {
621+
ASSERT_EQ(e.code().value(), static_cast<int>(sycl::errc::invalid))
622+
<< "sycl::exception code was not the expected "
623+
"sycl::errc::invalid.";
624+
// Expected path
625+
} catch (...) {
626+
FAIL() << "Unexpected exception was thrown in sycl::link.";
627+
}
628+
}

0 commit comments

Comments
 (0)