Skip to content

Commit 0ed9001

Browse files
committed
Fix issue of adoptive binaries and deallocation
Signed-off-by: Larsen, Steffen <[email protected]>
1 parent ca9d555 commit 0ed9001

File tree

3 files changed

+83
-29
lines changed

3 files changed

+83
-29
lines changed

sycl/source/detail/device_image_impl.hpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,22 @@ struct KernelCompilerBinaryInfo {
115115
include_pairs_t MIncludePairs;
116116
};
117117

118+
// Helper class to unregister shared SYCL binaries.
119+
class ManagedDeviceBinaries {
120+
public:
121+
ManagedDeviceBinaries(sycl_device_binaries &&Binaries)
122+
: MBinaries{Binaries} {}
123+
~ManagedDeviceBinaries() try {
124+
ProgramManager::getInstance().removeImages(MBinaries);
125+
syclex::detail::SYCL_JIT_Destroy(MBinaries);
126+
} catch (std::exception &e) {
127+
__SYCL_REPORT_EXCEPTION_TO_STREAM(
128+
"exception during unregistration of SYCL binaries", e);
129+
}
130+
private:
131+
sycl_device_binaries MBinaries;
132+
};
133+
118134
// The class is impl counterpart for sycl::device_image
119135
// It can represent a program in different states, kernel_id's it has and state
120136
// of specialization constants for it
@@ -550,12 +566,12 @@ class device_image_impl {
550566
return MRTCBinInfo && MRTCBinInfo->MLanguage == Lang;
551567
}
552568

553-
std::vector<std::shared_ptr<device_image_impl>>
554-
buildFromSource(const std::vector<device> Devices,
555-
const std::vector<std::string> &BuildOptions,
556-
std::string *LogPtr,
557-
const std::vector<std::string> &RegisteredKernelNames,
558-
std::vector<sycl_device_binaries> &OutDeviceBinaries) const {
569+
std::vector<std::shared_ptr<device_image_impl>> buildFromSource(
570+
const std::vector<device> Devices,
571+
const std::vector<std::string> &BuildOptions, std::string *LogPtr,
572+
const std::vector<std::string> &RegisteredKernelNames,
573+
std::vector<std::shared_ptr<ManagedDeviceBinaries>> &OutDeviceBinaries)
574+
const {
559575
assert(!std::holds_alternative<const RTDeviceBinaryImage *>(MBinImage));
560576
assert(MRTCBinInfo);
561577
assert(MOrigins & ImageOriginKernelCompiler);
@@ -666,7 +682,8 @@ class device_image_impl {
666682
Result.push_back(getSyclObjImpl(ImgWithDeps.getMain()));
667683
}
668684

669-
OutDeviceBinaries.push_back(std::move(Binaries));
685+
OutDeviceBinaries.emplace_back(
686+
std::make_shared<ManagedDeviceBinaries>(std::move(Binaries)));
670687
return Result;
671688
}
672689

sycl/source/detail/kernel_bundle_impl.hpp

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,11 @@ class kernel_bundle_impl {
302302
}
303303

304304
for (const detail::KernelBundleImplPtr &Bundle : Bundles) {
305-
306305
MDeviceImages.insert(MDeviceImages.end(), Bundle->MDeviceImages.begin(),
307306
Bundle->MDeviceImages.end());
307+
MDeviceBinaries.insert(MDeviceBinaries.end(),
308+
Bundle->MDeviceBinaries.begin(),
309+
Bundle->MDeviceBinaries.end());
308310
}
309311

310312
fillUniqueDeviceImages();
@@ -368,9 +370,10 @@ class kernel_bundle_impl {
368370

369371
// oneapi_ext_kernel_compiler
370372
// construct from built source files
371-
kernel_bundle_impl(const context &Context, const std::vector<device> &Devs,
372-
std::vector<device_image_plain> &&DevImgs,
373-
std::vector<sycl_device_binaries> &&DevBinaries)
373+
kernel_bundle_impl(
374+
const context &Context, const std::vector<device> &Devs,
375+
std::vector<device_image_plain> &&DevImgs,
376+
std::vector<std::shared_ptr<ManagedDeviceBinaries>> &&DevBinaries)
374377
: MContext(Context), MDevices(Devs),
375378
MUniqueDeviceImages(std::move(DevImgs)),
376379
MState(bundle_state::executable),
@@ -393,7 +396,7 @@ class kernel_bundle_impl {
393396
assert(allSourceBasedImages() && "All images must be source-based.");
394397

395398
std::vector<device_image_plain> NewDevImgs;
396-
std::vector<sycl_device_binaries> NewDeviceBinaries;
399+
std::vector<std::shared_ptr<ManagedDeviceBinaries>> NewDeviceBinaries;
397400
for (device_image_plain &DevImg : MUniqueDeviceImages) {
398401
std::vector<std::shared_ptr<device_image_impl>> NewDevImgImpls =
399402
getSyclObjImpl(DevImg)->buildFromSource(Devices, BuildOptions, LogPtr,
@@ -626,17 +629,6 @@ class kernel_bundle_impl {
626629
return true;
627630
}
628631

629-
~kernel_bundle_impl() {
630-
try {
631-
for (sycl_device_binaries &Binaries : MDeviceBinaries) {
632-
ProgramManager::getInstance().removeImages(Binaries);
633-
syclex::detail::SYCL_JIT_Destroy(Binaries);
634-
}
635-
} catch (std::exception &e) {
636-
__SYCL_REPORT_EXCEPTION_TO_STREAM("exception in ~kernel_bundle_impl", e);
637-
}
638-
}
639-
640632
bool hasSourceBasedImages() const noexcept {
641633
return std::any_of(begin(), end(), [](const device_image_plain &DevImg) {
642634
return getSyclObjImpl(DevImg)->getOriginMask() &
@@ -771,8 +763,8 @@ class kernel_bundle_impl {
771763
bundle_state MState;
772764

773765
// For sycl_jit, building from source may have produced sycl binaries that
774-
// this kernel_bundle now manages.
775-
std::vector<sycl_device_binaries> MDeviceBinaries;
766+
// the kernel_bundles now manage.
767+
std::vector<std::shared_ptr<ManagedDeviceBinaries>> MDeviceBinaries;
776768
};
777769

778770
} // namespace detail

sycl/test-e2e/KernelCompiler/sycl_join.cpp

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,12 @@ int main() {
121121
sycl::free(IntPtr, Q);
122122
}
123123

124-
exe_kb KBExe1 = syclex::build(KBSrc1);
125-
exe_kb KBExe2 = syclex::build(KBSrc2);
124+
auto KBExe1 = std::make_shared<exe_kb>(syclex::build(KBSrc1));
125+
auto KBExe2 = std::make_shared<exe_kb>(syclex::build(KBSrc2));
126126

127127
// Test joining of source-based executable kernel bundles.
128128
{
129-
std::vector<exe_kb> KBExes{KBExe1, KBExe2};
129+
std::vector<exe_kb> KBExes{*KBExe1, *KBExe2};
130130

131131
exe_kb KBExeJoined = sycl::join(KBExes);
132132
assert(KBExeJoined.ext_oneapi_has_kernel("TestKernel1"));
@@ -173,7 +173,7 @@ int main() {
173173
exe_kb RegularKBExe =
174174
sycl::get_kernel_bundle<sycl::bundle_state::executable>(
175175
Ctx, RegularSYCLKernelIDs);
176-
std::vector<exe_kb> KBExes{KBExe1, KBExe2, RegularKBExe};
176+
std::vector<exe_kb> KBExes{*KBExe1, *KBExe2, RegularKBExe};
177177

178178
exe_kb KBExeJoined = sycl::join(KBExes);
179179
assert(KBExeJoined.ext_oneapi_has_kernel("TestKernel1"));
@@ -235,5 +235,50 @@ int main() {
235235
sycl::free(IntPtr, Q);
236236
}
237237

238+
// Test joining of executable kernel bundles with the original bundles dying
239+
// before the parent.
240+
{
241+
std::vector<exe_kb> KBExes{*KBExe1, *KBExe2};
242+
243+
KBExe1.reset();
244+
KBExe2.reset();
245+
246+
exe_kb KBExeJoined = sycl::join(KBExes);
247+
assert(KBExeJoined.ext_oneapi_has_kernel("TestKernel1"));
248+
assert(KBExeJoined.ext_oneapi_has_kernel("TestKernel2"));
249+
250+
sycl::kernel K1 = KBExeJoined.ext_oneapi_get_kernel("TestKernel1");
251+
sycl::kernel K2 = KBExeJoined.ext_oneapi_get_kernel("TestKernel2");
252+
253+
int *IntPtr = sycl::malloc_shared<int>(1, Q);
254+
*IntPtr = 0;
255+
256+
Q.submit([&](sycl::handler &CGH) {
257+
CGH.set_args(IntPtr);
258+
CGH.single_task(K1);
259+
}).wait_and_throw();
260+
261+
if (*IntPtr != 42) {
262+
std::cout << "TestKernel1 in joined source-based executable bundles with "
263+
"dead parents failed: "
264+
<< *IntPtr << " != 42\n";
265+
++Failed;
266+
}
267+
268+
Q.submit([&](sycl::handler &CGH) {
269+
CGH.set_args(IntPtr);
270+
CGH.single_task(K2);
271+
}).wait_and_throw();
272+
273+
if (*IntPtr != 24) {
274+
std::cout << "TestKernel1 in joined source-based executable bundles with "
275+
"dead parents failed: "
276+
<< *IntPtr << " != 24\n";
277+
++Failed;
278+
}
279+
280+
sycl::free(IntPtr, Q);
281+
}
282+
238283
return Failed;
239284
}

0 commit comments

Comments
 (0)