Skip to content

Commit 41344ed

Browse files
[SYCL] Fix for native_specialization_constant() (#9085)
If MBinImage is nullptr, it leads to SIGSEGV. This patch fixes ProgramManager::link() function, so MBinImage will not be nullptr. Also changes link() signature to accept a single device image instead of vector, because we use it to pass the vector of one image, so it makes no sense. --------- Co-authored-by: Steffen Larsen <[email protected]>
1 parent c5d04bc commit 41344ed

File tree

5 files changed

+82
-57
lines changed

5 files changed

+82
-57
lines changed

sycl/source/detail/device_image_impl.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,15 @@ class device_image_impl {
112112
bool all_specialization_constant_native() const noexcept {
113113
// Specialization constants are natively supported in JIT mode on backends,
114114
// that are using SPIR-V as IR
115+
116+
// Not sure if it's possible currently, but probably it may happen if the
117+
// kernel bundle is created with interop function. Now the only one such
118+
// function is make_kernel(), but I'm not sure if it's even possible to
119+
// use spec constant with such kernel. So, in such case we need to check
120+
// if it's JIT or no somehow.
121+
assert(MBinImage &&
122+
"native_specialization_constant() called for unimplemented case");
123+
115124
auto IsJITSPIRVTarget = [](const char *Target) {
116125
return (strcmp(Target, __SYCL_PI_DEVICE_BINARY_TARGET_SPIRV64) == 0 ||
117126
strcmp(Target, __SYCL_PI_DEVICE_BINARY_TARGET_SPIRV32) == 0);

sycl/source/detail/kernel_bundle_impl.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,9 @@ class kernel_bundle_impl {
213213
}))
214214
continue;
215215

216-
const std::vector<device_image_plain> VectorOfOneImage{DeviceImage};
217216
std::vector<device_image_plain> LinkedResults =
218-
detail::ProgramManager::getInstance().link(VectorOfOneImage,
219-
MDevices, PropList);
217+
detail::ProgramManager::getInstance().link(DeviceImage, MDevices,
218+
PropList);
220219
MDeviceImages.insert(MDeviceImages.end(), LinkedResults.begin(),
221220
LinkedResults.end());
222221
}

sycl/source/detail/program_manager/program_manager.cpp

Lines changed: 44 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,15 +2105,13 @@ ProgramManager::compile(const device_image_plain &DeviceImage,
21052105
}
21062106

21072107
std::vector<device_image_plain>
2108-
ProgramManager::link(const std::vector<device_image_plain> &DeviceImages,
2108+
ProgramManager::link(const device_image_plain &DeviceImage,
21092109
const std::vector<device> &Devs,
21102110
const property_list &PropList) {
21112111
(void)PropList;
21122112

21132113
std::vector<pi_program> PIPrograms;
2114-
PIPrograms.reserve(DeviceImages.size());
2115-
for (const device_image_plain &DeviceImage : DeviceImages)
2116-
PIPrograms.push_back(getSyclObjImpl(DeviceImage)->get_program_ref());
2114+
PIPrograms.push_back(getSyclObjImpl(DeviceImage)->get_program_ref());
21172115

21182116
std::vector<pi_device> PIDevices;
21192117
PIDevices.reserve(Devs.size());
@@ -2123,14 +2121,12 @@ ProgramManager::link(const std::vector<device_image_plain> &DeviceImages,
21232121
std::string LinkOptionsStr;
21242122
applyLinkOptionsFromEnvironment(LinkOptionsStr);
21252123
if (LinkOptionsStr.empty()) {
2126-
for (const device_image_plain &DeviceImage : DeviceImages) {
2127-
const std::shared_ptr<device_image_impl> &InputImpl =
2128-
getSyclObjImpl(DeviceImage);
2129-
appendLinkOptionsFromImage(LinkOptionsStr,
2130-
*(InputImpl->get_bin_image_ref()));
2131-
}
2124+
const std::shared_ptr<device_image_impl> &InputImpl =
2125+
getSyclObjImpl(DeviceImage);
2126+
appendLinkOptionsFromImage(LinkOptionsStr,
2127+
*(InputImpl->get_bin_image_ref()));
21322128
}
2133-
const context &Context = getSyclObjImpl(DeviceImages[0])->get_context();
2129+
const context &Context = getSyclObjImpl(DeviceImage)->get_context();
21342130
const ContextImplPtr ContextImpl = getSyclObjImpl(Context);
21352131
const detail::plugin &Plugin = ContextImpl->getPlugin();
21362132

@@ -2152,55 +2148,53 @@ ProgramManager::link(const std::vector<device_image_plain> &DeviceImages,
21522148
std::shared_ptr<std::vector<kernel_id>> KernelIDs{new std::vector<kernel_id>};
21532149
std::vector<unsigned char> NewSpecConstBlob;
21542150
device_image_impl::SpecConstMapT NewSpecConstMap;
2155-
for (const device_image_plain &DeviceImage : DeviceImages) {
2156-
std::shared_ptr<device_image_impl> DeviceImageImpl =
2157-
getSyclObjImpl(DeviceImage);
21582151

2159-
// Duplicates are not expected here, otherwise piProgramLink should fail
2160-
KernelIDs->insert(KernelIDs->end(),
2161-
DeviceImageImpl->get_kernel_ids_ptr()->begin(),
2162-
DeviceImageImpl->get_kernel_ids_ptr()->end());
2152+
std::shared_ptr<device_image_impl> DeviceImageImpl =
2153+
getSyclObjImpl(DeviceImage);
21632154

2164-
// To be able to answer queries about specialziation constants, the new
2165-
// device image should have the specialization constants from all the linked
2166-
// images.
2167-
{
2168-
const std::lock_guard<std::mutex> SpecConstLock(
2169-
DeviceImageImpl->get_spec_const_data_lock());
2170-
2171-
// Copy all map entries to the new map. Since the blob will be copied to
2172-
// the end of the new blob we need to move the blob offset of each entry.
2173-
for (const auto &SpecConstIt :
2174-
DeviceImageImpl->get_spec_const_data_ref()) {
2175-
std::vector<device_image_impl::SpecConstDescT> &NewDescEntries =
2176-
NewSpecConstMap[SpecConstIt.first];
2177-
assert(NewDescEntries.empty() &&
2178-
"Specialization constant already exists in the map.");
2179-
NewDescEntries.reserve(SpecConstIt.second.size());
2180-
for (const device_image_impl::SpecConstDescT &SpecConstDesc :
2181-
SpecConstIt.second) {
2182-
device_image_impl::SpecConstDescT NewSpecConstDesc = SpecConstDesc;
2183-
NewSpecConstDesc.BlobOffset += NewSpecConstBlob.size();
2184-
NewDescEntries.push_back(std::move(NewSpecConstDesc));
2185-
}
2186-
}
2155+
// Duplicates are not expected here, otherwise piProgramLink should fail
2156+
KernelIDs->insert(KernelIDs->end(),
2157+
DeviceImageImpl->get_kernel_ids_ptr()->begin(),
2158+
DeviceImageImpl->get_kernel_ids_ptr()->end());
21872159

2188-
// Copy the blob from the device image into the new blob. This moves the
2189-
// offsets of the following blobs.
2190-
NewSpecConstBlob.insert(
2191-
NewSpecConstBlob.end(),
2192-
DeviceImageImpl->get_spec_const_blob_ref().begin(),
2193-
DeviceImageImpl->get_spec_const_blob_ref().end());
2160+
// To be able to answer queries about specialziation constants, the new
2161+
// device image should have the specialization constants from all the linked
2162+
// images.
2163+
{
2164+
const std::lock_guard<std::mutex> SpecConstLock(
2165+
DeviceImageImpl->get_spec_const_data_lock());
2166+
2167+
// Copy all map entries to the new map. Since the blob will be copied to
2168+
// the end of the new blob we need to move the blob offset of each entry.
2169+
for (const auto &SpecConstIt : DeviceImageImpl->get_spec_const_data_ref()) {
2170+
std::vector<device_image_impl::SpecConstDescT> &NewDescEntries =
2171+
NewSpecConstMap[SpecConstIt.first];
2172+
assert(NewDescEntries.empty() &&
2173+
"Specialization constant already exists in the map.");
2174+
NewDescEntries.reserve(SpecConstIt.second.size());
2175+
for (const device_image_impl::SpecConstDescT &SpecConstDesc :
2176+
SpecConstIt.second) {
2177+
device_image_impl::SpecConstDescT NewSpecConstDesc = SpecConstDesc;
2178+
NewSpecConstDesc.BlobOffset += NewSpecConstBlob.size();
2179+
NewDescEntries.push_back(std::move(NewSpecConstDesc));
2180+
}
21942181
}
2182+
2183+
// Copy the blob from the device image into the new blob. This moves the
2184+
// offsets of the following blobs.
2185+
NewSpecConstBlob.insert(NewSpecConstBlob.end(),
2186+
DeviceImageImpl->get_spec_const_blob_ref().begin(),
2187+
DeviceImageImpl->get_spec_const_blob_ref().end());
21952188
}
2189+
21962190
// device_image_impl expects kernel ids to be sorted for fast search
21972191
std::sort(KernelIDs->begin(), KernelIDs->end(), LessByHash<kernel_id>{});
21982192

2193+
auto BinImg = getSyclObjImpl(DeviceImage)->get_bin_image_ref();
21992194
DeviceImageImplPtr ExecutableImpl =
22002195
std::make_shared<detail::device_image_impl>(
2201-
/*BinImage=*/nullptr, Context, Devs, bundle_state::executable,
2202-
std::move(KernelIDs), LinkedProg, std::move(NewSpecConstMap),
2203-
std::move(NewSpecConstBlob));
2196+
BinImg, Context, Devs, bundle_state::executable, std::move(KernelIDs),
2197+
LinkedProg, std::move(NewSpecConstMap), std::move(NewSpecConstBlob));
22042198

22052199
// TODO: Make multiple sets of device images organized by devices they are
22062200
// compiled for.

sycl/source/detail/program_manager/program_manager.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,9 @@ class ProgramManager {
279279

280280
// Produces set of device images by convering input device images to object
281281
// the executable state
282-
std::vector<device_image_plain>
283-
link(const std::vector<device_image_plain> &DeviceImages,
284-
const std::vector<device> &Devs, const property_list &PropList);
282+
std::vector<device_image_plain> link(const device_image_plain &DeviceImages,
283+
const std::vector<device> &Devs,
284+
const property_list &PropList);
285285

286286
// Produces new device image by converting input device image to the
287287
// executable state

sycl/test-e2e/SpecConstants/2020/kernel-bundle-api.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,32 @@ bool test_set_and_get_on_device(sycl::queue q) {
266266
}
267267

268268
bool test_native_specialization_constant(sycl::queue q) {
269+
{
270+
q.submit([&](sycl::handler &cgh) {
271+
cgh.single_task<class Kernel>([=](sycl::kernel_handler h) {
272+
h.get_specialization_constant<int_id>();
273+
});
274+
});
275+
276+
auto inputBundle =
277+
sycl::get_kernel_bundle<class Kernel, sycl::bundle_state::input>(
278+
q.get_context(), {q.get_device()});
279+
auto objectBundle = sycl::compile(inputBundle);
280+
auto execBundleViaLink = sycl::link(objectBundle);
281+
auto BE = q.get_backend();
282+
bool expected = (BE == sycl::backend::opencl ||
283+
BE == sycl::backend::ext_oneapi_level_zero)
284+
? true
285+
: false;
286+
if (!check_value(expected,
287+
execBundleViaLink.native_specialization_constant(),
288+
"linked bundle native specialization constant"))
289+
return false;
290+
}
291+
269292
const auto always_false_selector = [](auto device_image) { return false; };
270293
auto bundle = sycl::get_kernel_bundle<sycl::bundle_state::executable>(
271294
q.get_context(), always_false_selector);
272-
return check_value(bundle.native_specialization_constant(), false,
295+
return check_value(false, bundle.native_specialization_constant(),
273296
"empty bundle native specialization constant");
274297
}

0 commit comments

Comments
 (0)